Skip to contentSkip to conversation

WM8994 MFD updates for 3.3

PATCH In review Mark Brown 2 participants 12 messages Nov 28, 2011 – Dec 12, 2011

Subsystems (5)
lore
Share & tools
lore

Mark Brown

author
#0 lore raw

cover WM8994 MFD updates for 3.3

The following patch series (and pull request) contains a bunch of updates I've previously posted for wm8994 but which haven't been merged plus a big update adding register cache support for the wm8994 driver which hasn't previously been posted. As there's a matching update for the ASoC driver for WM8994 removing the copy of the register cache there it'd be great if it were possible to merge this via the ASoC tree.

I've also got one more patch which depends on this lot converting the IRQ controller over to use the generic regmap IRQ controller which I'll post as well - that also depends on this series as the regmap interrupt controller relies on the register cache - so I'd also like to either pull the same branch into the regmap tree or merge both this and the regmap IRQ stuff via ASoC.

This seems like the easiest route from the point of view of bisection and cross tree issues - does that all sound OK to you?

The following changes since commit caca6a03d365883564885f2c1da3e88dcf65d139:

Linux 3.2-rc3 (2011-11-23 20:20:28 -0800)

are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/misc.git mfd/wm8994

Mark Brown (8):
mfd: Remove some unused functions in wm8894-irq
mfd: Add basic device tree binding for wm8994
mfd: Convert wm8994 to devm_kzalloc()
mfd: Disable more pulls on WM8994
mfd: Don't hard code the reset value for WM8994 devices
mfd: Define some additional wm8994 registers
mfd: Add wm8994 register access and default information
mfd: Enable register cache for wm8994 devices

 Documentation/devicetree/bindings/sound/wm8994.txt |   18 +
 drivers/mfd/Makefile                               |    2 +-
 drivers/mfd/wm8994-core.c                          |  121 +--
 drivers/mfd/wm8994-irq.c                           |   10 -
 drivers/mfd/wm8994-regmap.c                        | 1218 ++++++++++++++++++++
 drivers/mfd/wm8994.h                               |   24 +
 include/linux/mfd/wm8994/core.h                    |    2 -
 include/linux/mfd/wm8994/pdata.h                   |    6 +
 include/linux/mfd/wm8994/registers.h               |   96 ++
 sound/soc/codecs/wm8994-tables.c                   |   12 +-
 10 files changed, 1423 insertions(+), 86 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/sound/wm8994.txt
 create mode 100644 drivers/mfd/wm8994-regmap.c
 create mode 100644 drivers/mfd/wm8994.h
author
#1 lore raw

PATCH 1/8 mfd: Remove some unused functions in wm8894-irq

---
 drivers/mfd/wm8994-irq.c |   10 ----------
 1 files changed, 0 insertions(+), 10 deletions(-)
drivers/mfd/wm8994-irq.c +0 -10
index d682f7b..f9dd6b6 100644
@@ -140,16 +140,6 @@ static struct wm8994_irq_data wm8994_irqs[] = {
 	},
 };
 
-static inline int irq_data_to_status_reg(struct wm8994_irq_data *irq_data)
-{
-	return WM8994_INTERRUPT_STATUS_1 - 1 + irq_data->reg;
-}
-
-static inline int irq_data_to_mask_reg(struct wm8994_irq_data *irq_data)
-{
-	return WM8994_INTERRUPT_STATUS_1_MASK - 1 + irq_data->reg;
-}
-
 static inline struct wm8994_irq_data *irq_to_wm8994_irq(struct wm8994 *wm8994,
 							int irq)
 {
Signature · 1 line
1.7.7.3
author
#2 lore raw

PATCH 2/8 mfd: Add basic device tree binding for wm8994

Add a placeholder device tree binding for the wm8994 driver. At present the binding is essentially null as none of the platform data is supported, and at least some of that will depend on the pending regulator bindings.

---
 Documentation/devicetree/bindings/sound/wm8994.txt |   18 ++++++++++++++++++
 drivers/mfd/wm8994-core.c                          |    9 +++++++++
 2 files changed, 27 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/sound/wm8994.txt
Documentation/devicetree/bindings/sound/wm8994.txt new file +18 -0
new file mode 100644
index 0000000..7a7eb1e
@@ -0,0 +1,18 @@
+WM1811/WM8994/WM8958 audio CODEC
+
+These devices support both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+  - compatible : "wlf,wm1811", "wlf,wm8994", "wlf,wm8958"
+
+  - reg : the I2C address of the device for I2C, the chip select
+          number for SPI.
+
+Example:
+
+codec: wm8994@1a {
+	compatible = "wlf,wm8994";
+	reg = <0x1a>;
+};
drivers/mfd/wm8994-core.c +9 -0
index 5d6ba13..74d4746 100644
@@ -581,6 +581,14 @@ static void wm8994_device_exit(struct wm8994 *wm8994)
 	kfree(wm8994);
 }
 
+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);
+
 static int wm8994_i2c_probe(struct i2c_client *i2c,
 			    const struct i2c_device_id *id)
 {
@@ -633,6 +641,7 @@ static struct i2c_driver wm8994_i2c_driver = {
 		.name = "wm8994",
 		.owner = THIS_MODULE,
 		.pm = &wm8994_pm_ops,
+		.of_match_table = wm8994_of_match,
 	},
 	.probe = wm8994_i2c_probe,
 	.remove = wm8994_i2c_remove,
Signature · 1 line
1.7.7.3
author
#3 lore raw

PATCH 3/8 mfd: Convert wm8994 to devm_kzalloc()

In reply to Mark Brown
---
 drivers/mfd/wm8994-core.c |   16 +++++-----------
 1 files changed, 5 insertions(+), 11 deletions(-)
drivers/mfd/wm8994-core.c +5 -11
index 74d4746..a6846b0 100644
@@ -401,9 +401,9 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
 		goto err_regmap;
 	}
 
-	wm8994->supplies = kzalloc(sizeof(struct regulator_bulk_data) *
-				   wm8994->num_supplies,
-				   GFP_KERNEL);
+	wm8994->supplies = devm_kzalloc(wm8994->dev,
+					sizeof(struct regulator_bulk_data) *
+					wm8994->num_supplies, GFP_KERNEL);
 	if (!wm8994->supplies) {
 		ret = -ENOMEM;
 		goto err_regmap;
@@ -431,7 +431,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
 				 wm8994->supplies);
 	if (ret != 0) {
 		dev_err(wm8994->dev, "Failed to get supplies: %d\n", ret);
-		goto err_supplies;
+		goto err_regmap;
 	}
 
 	ret = regulator_bulk_enable(wm8994->num_supplies,
@@ -559,12 +559,9 @@ err_enable:
 			       wm8994->supplies);
 err_get:
 	regulator_bulk_free(wm8994->num_supplies, wm8994->supplies);
-err_supplies:
-	kfree(wm8994->supplies);
 err_regmap:
 	regmap_exit(wm8994->regmap);
 	mfd_remove_devices(wm8994->dev);
-	kfree(wm8994);
 	return ret;
 }
 
@@ -576,9 +573,7 @@ static void wm8994_device_exit(struct wm8994 *wm8994)
 	regulator_bulk_disable(wm8994->num_supplies,
 			       wm8994->supplies);
 	regulator_bulk_free(wm8994->num_supplies, wm8994->supplies);
-	kfree(wm8994->supplies);
 	regmap_exit(wm8994->regmap);
-	kfree(wm8994);
 }
 
 static const struct of_device_id wm8994_of_match[] = {
@@ -595,7 +590,7 @@ static int wm8994_i2c_probe(struct i2c_client *i2c,
 	struct wm8994 *wm8994;
 	int ret;
 
-	wm8994 = kzalloc(sizeof(struct wm8994), GFP_KERNEL);
+	wm8994 = devm_kzalloc(&i2c->dev, sizeof(struct wm8994), GFP_KERNEL);
 	if (wm8994 == NULL)
 		return -ENOMEM;
 
@@ -609,7 +604,6 @@ static int wm8994_i2c_probe(struct i2c_client *i2c,
 		ret = PTR_ERR(wm8994->regmap);
 		dev_err(wm8994->dev, "Failed to allocate register map: %d\n",
 			ret);
-		kfree(wm8994);
 		return ret;
 	}
 
Signature · 1 line
1.7.7.3
author
#4 lore raw

PATCH 4/8 mfd: Disable more pulls on WM8994

In reply to Mark Brown

Disable more pulls by default on WM8994 for a small current saving. Since some designs do leave SPKMODE floating provide platform data to allow that to be left enabled.

---
 drivers/mfd/wm8994-core.c        |   11 ++++++++---
 include/linux/mfd/wm8994/pdata.h |    6 ++++++
 2 files changed, 14 insertions(+), 3 deletions(-)
drivers/mfd/wm8994-core.c +8 -3
index a6846b0..c8956f2 100644
@@ -373,6 +373,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
 	struct wm8994_pdata *pdata = wm8994->dev->platform_data;
 	const char *devname;
 	int ret, i;
+	int pulls = 0;
 
 	dev_set_drvdata(wm8994->dev, wm8994);
 
@@ -515,12 +516,16 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
 		}
 
 		wm8994->ldo_ena_always_driven = pdata->ldo_ena_always_driven;
+
+		if (pdata->spkmode_pu)
+			pulls |= WM8994_SPKMODE_PU;
 	}
 
-	/* Disable LDO pulldowns while the device is active */
+	/* Disable unneeded pulls */
 	wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2,
-			WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD,
-			0);
+			WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD |
+			WM8994_SPKMODE_PU | WM8994_CSNADDR_PD,
+			pulls);
 
 	/* In some system designs where the regulators are not in use,
 	 * we can achieve a small reduction in leakage currents by
include/linux/mfd/wm8994/pdata.h +6 -0
index ea32f30..54e2fef 100644
@@ -174,6 +174,12 @@ struct wm8994_pdata {
 	 * consumption will rise.
 	 */
 	bool ldo_ena_always_driven;
+
+	/*
+	 * SPKMODE must be pulled internally by the device on this
+	 * system.
+	 */
+	bool spkmode_pu;
 };
 
 #endif
Signature · 1 line
1.7.7.3
author
#5 lore raw

PATCH 5/8 mfd: Don't hard code the reset value for WM8994 devices

In reply to Mark Brown
---
 drivers/mfd/wm8994-core.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)
drivers/mfd/wm8994-core.c +2 -1
index c8956f2..0167694 100644
@@ -276,7 +276,8 @@ static int wm8994_suspend(struct device *dev)
 	/* Explicitly put the device into reset in case regulators
 	 * don't get disabled in order to ensure consistent restart.
 	 */
-	wm8994_reg_write(wm8994, WM8994_SOFTWARE_RESET, 0x8994);
+	wm8994_reg_write(wm8994, WM8994_SOFTWARE_RESET,
+			 wm8994_reg_read(wm8994, WM8994_SOFTWARE_RESET));
 
 	wm8994->suspended = true;
 
Signature · 1 line
1.7.7.3
author
#6 lore raw

PATCH 6/8 mfd: Define some additional wm8994 registers

In reply to Mark Brown

Add a bunch of definitions for wm8994 registers that are not currently used by software.

---
 include/linux/mfd/wm8994/registers.h |   96 ++++++++++++++++++++++++++++++++++
 sound/soc/codecs/wm8994-tables.c     |   12 ++--
 2 files changed, 102 insertions(+), 6 deletions(-)
include/linux/mfd/wm8994/registers.h +96 -0
index 83a9cae..8317b19 100644
@@ -95,11 +95,15 @@
 #define WM8994_FLL1_CONTROL_3                   0x222
 #define WM8994_FLL1_CONTROL_4                   0x223
 #define WM8994_FLL1_CONTROL_5                   0x224
+#define WM8958_FLL1_EFS_1                       0x226
+#define WM8958_FLL1_EFS_2                       0x227
 #define WM8994_FLL2_CONTROL_1                   0x240
 #define WM8994_FLL2_CONTROL_2                   0x241
 #define WM8994_FLL2_CONTROL_3                   0x242
 #define WM8994_FLL2_CONTROL_4                   0x243
 #define WM8994_FLL2_CONTROL_5                   0x244
+#define WM8958_FLL2_EFS_1                       0x246
+#define WM8958_FLL2_EFS_2                       0x247
 #define WM8994_AIF1_CONTROL_1                   0x300
 #define WM8994_AIF1_CONTROL_2                   0x301
 #define WM8994_AIF1_MASTER_SLAVE                0x302
@@ -116,6 +120,7 @@
 #define WM8994_AIF2DAC_LRCLK                    0x315
 #define WM8994_AIF2DAC_DATA                     0x316
 #define WM8994_AIF2ADC_DATA                     0x317
+#define WM1811_AIF2TX_CONTROL                   0x318
 #define WM8958_AIF3_CONTROL_1                   0x320
 #define WM8958_AIF3_CONTROL_2                   0x321
 #define WM8958_AIF3DAC_DATA                     0x322
@@ -166,6 +171,7 @@
 #define WM8994_AIF1_DAC1_EQ_BAND_5_A            0x491
 #define WM8994_AIF1_DAC1_EQ_BAND_5_B            0x492
 #define WM8994_AIF1_DAC1_EQ_BAND_5_PG           0x493
+#define WM8994_AIF1_DAC1_EQ_BAND_1_C            0x494
 #define WM8994_AIF1_DAC2_EQ_GAINS_1             0x4A0
 #define WM8994_AIF1_DAC2_EQ_GAINS_2             0x4A1
 #define WM8994_AIF1_DAC2_EQ_BAND_1_A            0x4A2
@@ -186,6 +192,7 @@
 #define WM8994_AIF1_DAC2_EQ_BAND_5_A            0x4B1
 #define WM8994_AIF1_DAC2_EQ_BAND_5_B            0x4B2
 #define WM8994_AIF1_DAC2_EQ_BAND_5_PG           0x4B3
+#define WM8994_AIF1_DAC2_EQ_BAND_1_C            0x4B4
 #define WM8994_AIF2_ADC_LEFT_VOLUME             0x500
 #define WM8994_AIF2_ADC_RIGHT_VOLUME            0x501
 #define WM8994_AIF2_DAC_LEFT_VOLUME             0x502
@@ -219,6 +226,7 @@
 #define WM8994_AIF2_EQ_BAND_5_A                 0x591
 #define WM8994_AIF2_EQ_BAND_5_B                 0x592
 #define WM8994_AIF2_EQ_BAND_5_PG                0x593
+#define WM8994_AIF2_EQ_BAND_1_C                 0x594
 #define WM8994_DAC1_MIXER_VOLUMES               0x600
 #define WM8994_DAC1_LEFT_MIXER_ROUTING          0x601
 #define WM8994_DAC1_RIGHT_MIXER_ROUTING         0x602
@@ -264,7 +272,43 @@
 #define WM8958_DSP2_RELEASETIME                 0xA03
 #define WM8958_DSP2_VERMAJMIN                   0xA04
 #define WM8958_DSP2_VERBUILD                    0xA05
+#define WM8958_DSP2_TESTREG                     0xA06
+#define WM8958_DSP2_XORREG                      0xA07
+#define WM8958_DSP2_SHIFTMAXX                   0xA08
+#define WM8958_DSP2_SHIFTMAXY                   0xA09
+#define WM8958_DSP2_SHIFTMAXZ                   0xA0A
+#define WM8958_DSP2_SHIFTMAXEXTLO               0xA0B
+#define WM8958_DSP2_AESSELECT                   0xA0C
 #define WM8958_DSP2_EXECCONTROL                 0xA0D
+#define WM8958_DSP2_SAMPLEBREAK                 0xA0E
+#define WM8958_DSP2_COUNTBREAK                  0xA0F
+#define WM8958_DSP2_INTSTATUS                   0xA10
+#define WM8958_DSP2_EVENTSTATUS                 0xA11
+#define WM8958_DSP2_INTMASK                     0xA12
+#define WM8958_DSP2_CONFIGDWIDTH                0xA13
+#define WM8958_DSP2_CONFIGINSTR                 0xA14
+#define WM8958_DSP2_CONFIGDMEM                  0xA15
+#define WM8958_DSP2_CONFIGDELAYS                0xA16
+#define WM8958_DSP2_CONFIGNUMIO                 0xA17
+#define WM8958_DSP2_CONFIGEXTDEPTH              0xA18
+#define WM8958_DSP2_CONFIGMULTIPLIER            0xA19
+#define WM8958_DSP2_CONFIGCTRLDWIDTH            0xA1A
+#define WM8958_DSP2_CONFIGPIPELINE              0xA1B
+#define WM8958_DSP2_SHIFTMAXEXTHI               0xA1C
+#define WM8958_DSP2_SWVERSIONREG                0xA1D
+#define WM8958_DSP2_CONFIGXMEM                  0xA1E
+#define WM8958_DSP2_CONFIGYMEM                  0xA1F
+#define WM8958_DSP2_CONFIGZMEM                  0xA20
+#define WM8958_FW_BUILD_1                       0x2000
+#define WM8958_FW_BUILD_0                       0x2001
+#define WM8958_FW_ID_1                          0x2002
+#define WM8958_FW_ID_0                          0x2003
+#define WM8958_FW_MAJOR_1                       0x2004
+#define WM8958_FW_MAJOR_0                       0x2005
+#define WM8958_FW_MINOR_1                       0x2006
+#define WM8958_FW_MINOR_0                       0x2007
+#define WM8958_FW_PATCH_1                       0x2008
+#define WM8958_FW_PATCH_0                       0x2009
 #define WM8958_MBC_BAND_2_LOWER_CUTOFF_C1_1     0x2200
 #define WM8958_MBC_BAND_2_LOWER_CUTOFF_C1_2     0x2201
 #define WM8958_MBC_BAND_2_LOWER_CUTOFF_C2_1     0x2202
@@ -333,6 +377,14 @@
 #define WM8958_MBC_B2_PG2_2                     0x242D
 #define WM8958_MBC_B1_PG2_1                     0x242E
 #define WM8958_MBC_B1_PG2_2                     0x242F
+#define WM8958_MBC_CROSSOVER_1                  0x2600
+#define WM8958_MBC_CROSSOVER_2                  0x2601
+#define WM8958_MBC_HPF_1                        0x2602
+#define WM8958_MBC_HPF_2                        0x2603
+#define WM8958_MBC_LPF_1                        0x2606
+#define WM8958_MBC_LPF_2                        0x2607
+#define WM8958_MBC_RMS_LIMIT_1                  0x260A
+#define WM8958_MBC_RMS_LIMIT_2                  0x260B
 #define WM8994_WRITE_SEQUENCER_0                0x3000
 #define WM8994_WRITE_SEQUENCER_1                0x3001
 #define WM8994_WRITE_SEQUENCER_2                0x3002
@@ -2389,6 +2441,10 @@
 /*
  * R548 (0x224) - FLL1 Control (5)
  */
+#define WM8958_FLL1_BYP                         0x8000  /* FLL1_BYP */
+#define WM8958_FLL1_BYP_MASK                    0x8000  /* FLL1_BYP */
+#define WM8958_FLL1_BYP_SHIFT                       15  /* FLL1_BYP */
+#define WM8958_FLL1_BYP_WIDTH                        1  /* FLL1_BYP */
 #define WM8994_FLL1_FRC_NCO_VAL_MASK            0x1F80  /* FLL1_FRC_NCO_VAL - [12:7] */
 #define WM8994_FLL1_FRC_NCO_VAL_SHIFT                7  /* FLL1_FRC_NCO_VAL - [12:7] */
 #define WM8994_FLL1_FRC_NCO_VAL_WIDTH                6  /* FLL1_FRC_NCO_VAL - [12:7] */
@@ -2404,6 +2460,24 @@
 #define WM8994_FLL1_REFCLK_SRC_WIDTH                 2  /* FLL1_REFCLK_SRC - [1:0] */
 
 /*
+ * R550 (0x226) - FLL1 EFS 1
+ */
+#define WM8958_FLL1_LAMBDA_MASK                 0xFFFF  /* FLL1_LAMBDA - [15:0] */
+#define WM8958_FLL1_LAMBDA_SHIFT                     0  /* FLL1_LAMBDA - [15:0] */
+#define WM8958_FLL1_LAMBDA_WIDTH                    16  /* FLL1_LAMBDA - [15:0] */
+
+/*
+ * R551 (0x227) - FLL1 EFS 2
+ */
+#define WM8958_FLL1_LFSR_SEL_MASK               0x0006  /* FLL1_LFSR_SEL - [2:1] */
+#define WM8958_FLL1_LFSR_SEL_SHIFT                   1  /* FLL1_LFSR_SEL - [2:1] */
+#define WM8958_FLL1_LFSR_SEL_WIDTH                   2  /* FLL1_LFSR_SEL - [2:1] */
+#define WM8958_FLL1_EFS_ENA                     0x0001  /* FLL1_EFS_ENA */
+#define WM8958_FLL1_EFS_ENA_MASK                0x0001  /* FLL1_EFS_ENA */
+#define WM8958_FLL1_EFS_ENA_SHIFT                    0  /* FLL1_EFS_ENA */
+#define WM8958_FLL1_EFS_ENA_WIDTH                    1  /* FLL1_EFS_ENA */
+
+/*
  * R576 (0x240) - FLL2 Control (1)
  */
 #define WM8994_FLL2_FRAC                        0x0004  /* FLL2_FRAC */
@@ -2452,6 +2526,10 @@
 /*
  * R580 (0x244) - FLL2 Control (5)
  */
+#define WM8958_FLL2_BYP                         0x8000  /* FLL2_BYP */
+#define WM8958_FLL2_BYP_MASK                    0x8000  /* FLL2_BYP */
+#define WM8958_FLL2_BYP_SHIFT                       15  /* FLL2_BYP */
+#define WM8958_FLL2_BYP_WIDTH                        1  /* FLL2_BYP */
 #define WM8994_FLL2_FRC_NCO_VAL_MASK            0x1F80  /* FLL2_FRC_NCO_VAL - [12:7] */
 #define WM8994_FLL2_FRC_NCO_VAL_SHIFT                7  /* FLL2_FRC_NCO_VAL - [12:7] */
 #define WM8994_FLL2_FRC_NCO_VAL_WIDTH                6  /* FLL2_FRC_NCO_VAL - [12:7] */
@@ -2467,6 +2545,24 @@
 #define WM8994_FLL2_REFCLK_SRC_WIDTH                 2  /* FLL2_REFCLK_SRC - [1:0] */
 
 /*
+ * R582 (0x246) - FLL2 EFS 1
+ */
+#define WM8958_FLL2_LAMBDA_MASK                 0xFFFF  /* FLL2_LAMBDA - [15:0] */
+#define WM8958_FLL2_LAMBDA_SHIFT                     0  /* FLL2_LAMBDA - [15:0] */
+#define WM8958_FLL2_LAMBDA_WIDTH                    16  /* FLL2_LAMBDA - [15:0] */
+
+/*
+ * R583 (0x247) - FLL2 EFS 2
+ */
+#define WM8958_FLL2_LFSR_SEL_MASK               0x0006  /* FLL2_LFSR_SEL - [2:1] */
+#define WM8958_FLL2_LFSR_SEL_SHIFT                   1  /* FLL2_LFSR_SEL - [2:1] */
+#define WM8958_FLL2_LFSR_SEL_WIDTH                   2  /* FLL2_LFSR_SEL - [2:1] */
+#define WM8958_FLL2_EFS_ENA                     0x0001  /* FLL2_EFS_ENA */
+#define WM8958_FLL2_EFS_ENA_MASK                0x0001  /* FLL2_EFS_ENA */
+#define WM8958_FLL2_EFS_ENA_SHIFT                    0  /* FLL2_EFS_ENA */
+#define WM8958_FLL2_EFS_ENA_WIDTH                    1  /* FLL2_EFS_ENA */
+
+/*
  * R768 (0x300) - AIF1 Control (1)
  */
 #define WM8994_AIF1ADCL_SRC                     0x8000  /* AIF1ADCL_SRC */
sound/soc/codecs/wm8994-tables.c +6 -6
index df5a8b9..6ed19d9 100644
@@ -78,7 +78,7 @@ const struct wm8994_access_mask wm8994_access_masks[WM8994_CACHE_SIZE] = {
 	{ 0x0000, 0x0000 }, /* R74 */
 	{ 0x0000, 0x0000 }, /* R75 */
 	{ 0x8000, 0x8000 }, /* R76    - Charge Pump (1) */
-	{ 0x0000, 0x0000 }, /* R77 */
+	{ 0x8000, 0x8000 }, /* R77    - Charge Pump (2) */
 	{ 0x0000, 0x0000 }, /* R78 */
 	{ 0x0000, 0x0000 }, /* R79 */
 	{ 0x0000, 0x0000 }, /* R80 */
@@ -1651,7 +1651,7 @@ const u16 wm8994_reg_defaults[WM8994_CACHE_SIZE] = {
 	0x0000,     /* R74 */
 	0x0000,     /* R75 */
 	0x1F25,     /* R76    - Charge Pump (1) */
-	0x0000,     /* R77 */
+	0xAB19,     /* R77    - Charge Pump (2) */
 	0x0000,     /* R78 */
 	0x0000,     /* R79 */
 	0x0000,     /* R80 */
@@ -2124,8 +2124,8 @@ const u16 wm8994_reg_defaults[WM8994_CACHE_SIZE] = {
 	0x0000,     /* R547   - FLL1 Control (4) */
 	0x0C80,     /* R548   - FLL1 Control (5) */
 	0x0000,     /* R549 */
-	0x0000,     /* R550 */
-	0x0000,     /* R551 */
+	0x0000,     /* R550   - FLL1 EFS 1 */
+	0x0006,     /* R551   - FLL1 EFS 2 */
 	0x0000,     /* R552 */
 	0x0000,     /* R553 */
 	0x0000,     /* R554 */
@@ -2156,8 +2156,8 @@ const u16 wm8994_reg_defaults[WM8994_CACHE_SIZE] = {
 	0x0000,     /* R579   - FLL2 Control (4) */
 	0x0C80,     /* R580   - FLL2 Control (5) */
 	0x0000,     /* R581 */
-	0x0000,     /* R582 */
-	0x0000,     /* R583 */
+	0x0000,     /* R582   - FLL2 EFS 1 */
+	0x0006,     /* R583   - FLL2 EFS 2 */
 	0x0000,     /* R584 */
 	0x0000,     /* R585 */
 	0x0000,     /* R586 */
Signature · 1 line
1.7.7.3
author
#7 lore raw

PATCH 7/8 mfd: Add wm8994 register access and default information

In reply to Mark Brown

Describe the register map to the regmap core so that we can use its diagnostic features and cache support. This is split out from the patch using it due to the size so that the actual code change is a bit clearer.

As the various devices are supersets of each other the access maps are built up by layering the functions on top of each other, though the interface for specifying the register defaults isn't currently amenable to this.

---
 drivers/mfd/Makefile        |    2 +-
 drivers/mfd/wm8994-regmap.c | 1218 +++++++++++++++++++++++++++++++++++++++++++
 drivers/mfd/wm8994.h        |   24 +
 3 files changed, 1243 insertions(+), 1 deletions(-)
 create mode 100644 drivers/mfd/wm8994-regmap.c
 create mode 100644 drivers/mfd/wm8994.h
drivers/mfd/Makefile +1 -1
index b2292eb..ef0ae7f 100644
@@ -31,7 +31,7 @@ wm8350-objs			:= wm8350-core.o wm8350-regmap.o wm8350-gpio.o
 wm8350-objs			+= wm8350-irq.o
 obj-$(CONFIG_MFD_WM8350)	+= wm8350.o
 obj-$(CONFIG_MFD_WM8350_I2C)	+= wm8350-i2c.o
-obj-$(CONFIG_MFD_WM8994)	+= wm8994-core.o wm8994-irq.o
+obj-$(CONFIG_MFD_WM8994)	+= wm8994-core.o wm8994-irq.o wm8994-regmap.o
 
 obj-$(CONFIG_TPS6105X)		+= tps6105x.o
 obj-$(CONFIG_TPS65010)		+= tps65010.o
drivers/mfd/wm8994-regmap.c new file +1218 -0

1,218 lines not on this page · raw message

drivers/mfd/wm8994.h new file +24 -0
new file mode 100644
index 0000000..bf2bdc1
@@ -0,0 +1,24 @@
+/*
+ * wm8994.h -- WM8994 MFD internals
+ *
+ * Copyright 2011 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <[email protected]>
+ *
+ *  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.
+ *
+ */
+
+#ifndef __MFD_WM8994_H__
+#define __MFD_WM8994_H__
+
+#include <linux/regmap.h>
+
+extern struct regmap_config wm1811_regmap_config;
+extern struct regmap_config wm8994_regmap_config;
+extern struct regmap_config wm8958_regmap_config;
+
+#endif
Signature · 1 line
1.7.7.3
author
#8 lore raw

PATCH 8/8 mfd: Enable register cache for wm8994 devices

In reply to Mark Brown

As part of this we provide information about the registers that exist in the device to the regmap core, drop the small amount of cache that the core had been using and let regmap do the sync.

---
 drivers/mfd/wm8994-core.c       |   82 ++++++++++++++------------------------
 include/linux/mfd/wm8994/core.h |    2 -
 2 files changed, 30 insertions(+), 54 deletions(-)
drivers/mfd/wm8994-core.c +30 -52
index 0167694..aafac5b 100644
@@ -28,11 +28,7 @@
 #include <linux/mfd/wm8994/pdata.h>
 #include <linux/mfd/wm8994/registers.h>
 
-static int wm8994_read(struct wm8994 *wm8994, unsigned short reg,
-		       int bytes, void *dest)
-{
-	return regmap_raw_read(wm8994->regmap, reg, dest, bytes);
-}
+#include "wm8994.h"
 
 /**
  * wm8994_reg_read: Read a single WM8994 register.
@@ -68,12 +64,6 @@ int wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg,
 	return regmap_bulk_read(wm8994->regmap, reg, buf, count);
 }
 
-static int wm8994_write(struct wm8994 *wm8994, unsigned short reg,
-			int bytes, const void *src)
-{
-	return regmap_raw_write(wm8994->regmap, reg, src, bytes);
-}
-
 /**
  * wm8994_reg_write: Write a single WM8994 register.
  *
@@ -258,27 +248,14 @@ static int wm8994_suspend(struct device *dev)
 				WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD,
 				WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD);
 
-	/* GPIO configuration state is saved here since we may be configuring
-	 * the GPIO alternate functions even if we're not using the gpiolib
-	 * driver for them.
-	 */
-	ret = wm8994_read(wm8994, WM8994_GPIO_1, WM8994_NUM_GPIO_REGS * 2,
-			  &wm8994->gpio_regs);
-	if (ret < 0)
-		dev_err(dev, "Failed to save GPIO registers: %d\n", ret);
-
-	/* For similar reasons we also stash the regulator states */
-	ret = wm8994_read(wm8994, WM8994_LDO_1, WM8994_NUM_LDO_REGS * 2,
-			  &wm8994->ldo_regs);
-	if (ret < 0)
-		dev_err(dev, "Failed to save LDO registers: %d\n", ret);
-
 	/* Explicitly put the device into reset in case regulators
 	 * don't get disabled in order to ensure consistent restart.
 	 */
 	wm8994_reg_write(wm8994, WM8994_SOFTWARE_RESET,
 			 wm8994_reg_read(wm8994, WM8994_SOFTWARE_RESET));
 
+	regcache_mark_dirty(wm8994->regmap);
+
 	wm8994->suspended = true;
 
 	ret = regulator_bulk_disable(wm8994->num_supplies,
@@ -294,7 +271,7 @@ static int wm8994_suspend(struct device *dev)
 static int wm8994_resume(struct device *dev)
 {
 	struct wm8994 *wm8994 = dev_get_drvdata(dev);
-	int ret, i;
+	int ret;
 
 	/* We may have lied to the PM core about suspending */
 	if (!wm8994->suspended)
@@ -307,27 +284,12 @@ static int wm8994_resume(struct device *dev)
 		return ret;
 	}
 
-	/* Write register at a time as we use the cache on the CPU so store
-	 * it in native endian.
-	 */
-	for (i = 0; i < ARRAY_SIZE(wm8994->irq_masks_cur); i++) {
-		ret = wm8994_reg_write(wm8994, WM8994_INTERRUPT_STATUS_1_MASK
-				       + i, wm8994->irq_masks_cur[i]);
-		if (ret < 0)
-			dev_err(dev, "Failed to restore interrupt masks: %d\n",
-				ret);
+	ret = regcache_sync(wm8994->regmap);
+	if (ret != 0) {
+		dev_err(dev, "Failed to restore register map: %d\n", ret);
+		goto err_enable;
 	}
 
-	ret = wm8994_write(wm8994, WM8994_LDO_1, WM8994_NUM_LDO_REGS * 2,
-			   &wm8994->ldo_regs);
-	if (ret < 0)
-		dev_err(dev, "Failed to restore LDO registers: %d\n", ret);
-
-	ret = wm8994_write(wm8994, WM8994_GPIO_1, WM8994_NUM_GPIO_REGS * 2,
-			   &wm8994->gpio_regs);
-	if (ret < 0)
-		dev_err(dev, "Failed to restore GPIO registers: %d\n", ret);
-
 	/* Disable LDO pulldowns while the device is active */
 	wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2,
 			WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD,
@@ -336,6 +298,11 @@ static int wm8994_resume(struct device *dev)
 	wm8994->suspended = false;
 
 	return 0;
+
+err_enable:
+	regulator_bulk_disable(wm8994->num_supplies, wm8994->supplies);
+
+	return ret;
 }
 #endif
 
@@ -361,11 +328,6 @@ static int wm8994_ldo_in_use(struct wm8994_pdata *pdata, int ldo)
 }
 #endif
 
-static struct regmap_config wm8994_regmap_config = {
-	.reg_bits = 16,
-	.val_bits = 16,
-};
-
 /*
  * Instantiate the generic non-control parts of the device.
  */
@@ -594,6 +556,7 @@ static int wm8994_i2c_probe(struct i2c_client *i2c,
 			    const struct i2c_device_id *id)
 {
 	struct wm8994 *wm8994;
+	struct regmap_config *regmap_config;
 	int ret;
 
 	wm8994 = devm_kzalloc(&i2c->dev, sizeof(struct wm8994), GFP_KERNEL);
@@ -605,7 +568,22 @@ static int wm8994_i2c_probe(struct i2c_client *i2c,
 	wm8994->irq = i2c->irq;
 	wm8994->type = id->driver_data;
 
-	wm8994->regmap = regmap_init_i2c(i2c, &wm8994_regmap_config);
+	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\n", wm8994->type);
+		return -EINVAL;
+	}
+
+	wm8994->regmap = regmap_init_i2c(i2c, regmap_config);
 	if (IS_ERR(wm8994->regmap)) {
 		ret = PTR_ERR(wm8994->regmap);
 		dev_err(wm8994->dev, "Failed to allocate register map: %d\n",
include/linux/mfd/wm8994/core.h +0 -2
index f44bdb7..d98593d 100644
@@ -70,8 +70,6 @@ struct wm8994 {
 
 	/* Used over suspend/resume */
 	bool suspended;
-	u16 ldo_regs[WM8994_NUM_LDO_REGS];
-	u16 gpio_regs[WM8994_NUM_GPIO_REGS];
 
 	struct regulator_dev *dbvdd;
 	int num_supplies;
Signature · 1 line
1.7.7.3
author
#9 lore raw

Re: [PATCH 8/8] mfd: Enable register cache for wm8994 devices

Quoted 3 lines · Mark Brown

As part of this we provide information about the registers that exist in the device to the regmap core, drop the small amount of cache that the core had been using and let regmap do the sync.

Oh, and I forgot that this one depends on a regmap patch (regmap: Track if the register cache is dirty and suppress unneeded syncs). I've rebuilt the branch with the appropriate merge in it.

author
#10 lore raw

PATCH 1/1 mfd: Convert wm8994 to use generic regmap irq_chip

In reply to Mark Brown

Factor out the irq_chip implementation, substantially reducing the code size for the driver.

---
 drivers/mfd/Kconfig             |    1 +
 drivers/mfd/wm8994-irq.c        |  196 +++++++--------------------------------
 include/linux/mfd/wm8994/core.h |    3 +-
 3 files changed, 35 insertions(+), 165 deletions(-)
drivers/mfd/Kconfig +1 -0
index f1391c2..017f6db 100644
@@ -477,6 +477,7 @@ config MFD_WM8994
 	bool "Support Wolfson Microelectronics WM8994"
 	select MFD_CORE
 	select REGMAP_I2C
+	select REGMAP_IRQ
 	depends on I2C=y && GENERIC_HARDIRQS
 	help
 	  The WM8994 is a highly integrated hi-fi CODEC designed for
drivers/mfd/wm8994-irq.c +33 -163

307 lines not on this page · raw message

include/linux/mfd/wm8994/core.h +1 -2
index d98593d..b9a44e7 100644
@@ -65,8 +65,7 @@ struct wm8994 {
 	int irq_base;
 
 	int irq;
-	u16 irq_masks_cur[WM8994_NUM_IRQ_REGS];
-	u16 irq_masks_cache[WM8994_NUM_IRQ_REGS];
+	struct regmap_irq_chip_data *irq_data;
 
 	/* Used over suspend/resume */
 	bool suspended;
Signature · 1 line
1.7.7.3
Acked-by on the v1 series
#11 lore raw
In reply to Mark Brown

Hi Mark,

Quoted 14 lines · Mark Brown

The following patch series (and pull request) contains a bunch of updates I've previously posted for wm8994 but which haven't been merged plus a big update adding register cache support for the wm8994 driver which hasn't previously been posted. As there's a matching update for the ASoC driver for WM8994 removing the copy of the register cache there it'd be great if it were possible to merge this via the ASoC tree.

I've also got one more patch which depends on this lot converting the IRQ controller over to use the generic regmap IRQ controller which I'll post as well - that also depends on this series as the regmap interrupt controller relies on the register cache - so I'd also like to either pull the same branch into the regmap tree or merge both this and the regmap IRQ stuff via ASoC.

Quoted 2 lines

This seems like the easiest route from the point of view of bisection and cross tree issues - does that all sound OK to you?

Yes, that sounds good. Please add my:

to this patchset.

Cheers,
Samuel.

Signature · 2 lines
Intel Open Source Technology Centre
http://oss.intel.com/