ASoC: WM8903: Add device tree binding
authorStephen Warren <swarren@nvidia.com>
Fri, 2 Dec 2011 22:08:41 +0000 (15:08 -0700)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Tue, 6 Dec 2011 10:29:22 +0000 (10:29 +0000)
Document the device tree binding for the WM8903 codec, and modify the
driver to extract platform data from the device tree, if present.

Based on work by John Bonesio, but significantly reworked since then.

Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Documentation/devicetree/bindings/sound/wm8903.txt [new file with mode: 0644]
sound/soc/codecs/wm8903.c

diff --git a/Documentation/devicetree/bindings/sound/wm8903.txt b/Documentation/devicetree/bindings/sound/wm8903.txt
new file mode 100644 (file)
index 0000000..f102cbc
--- /dev/null
@@ -0,0 +1,50 @@
+WM8903 audio CODEC
+
+This device supports I2C only.
+
+Required properties:
+
+  - compatible : "wlf,wm8903"
+
+  - reg : the I2C address of the device.
+
+  - gpio-controller : Indicates this device is a GPIO controller.
+
+  - #gpio-cells : Should be two. The first cell is the pin number and the
+    second cell is used to specify optional parameters (currently unused).
+
+Optional properties:
+
+  - interrupts : The interrupt line the codec is connected to.
+
+  - micdet-cfg : Default register value for R6 (Mic Bias). If absent, the
+    default is 0.
+
+  - micdet-delay : The debounce delay for microphone detection in mS. If
+    absent, the default is 100.
+
+  - gpio-cfg : A list of GPIO configuration register values. The list must
+    be 5 entries long. If absent, no configuration of these registers is
+    performed. If any entry has the value 0xffffffff, that GPIO's
+    configuration will not be modified.
+
+Example:
+
+codec: wm8903@1a {
+       compatible = "wlf,wm8903";
+       reg = <0x1a>;
+       interrupts = < 347 >;
+
+       gpio-controller;
+       #gpio-cells = <2>;
+
+       micdet-cfg = <0>;
+       micdet-delay = <100>;
+       gpio-cfg = <
+               0x0600 /* DMIC_LR, output */
+               0x0680 /* DMIC_DAT, input */
+               0x0000 /* GPIO, output, low */
+               0x0200 /* Interrupt, output */
+               0x01a0 /* BCLK, input, active high */
+       >;
+};
index b4f2c906b2f335914227b905537ec18c1c1f3663..adfbefaaab21d4142ae867dbc73410b41b7412c2 100644 (file)
@@ -2070,6 +2070,49 @@ static int wm8903_set_pdata_irq_trigger(struct i2c_client *i2c,
        return 0;
 }
 
+static int wm8903_set_pdata_from_of(struct i2c_client *i2c,
+                                   struct wm8903_platform_data *pdata)
+{
+       const struct device_node *np = i2c->dev.of_node;
+       u32 val32;
+       int i;
+
+       if (of_property_read_u32(np, "micdet-cfg", &val32) >= 0)
+               pdata->micdet_cfg = val32;
+
+       if (of_property_read_u32(np, "micdet-delay", &val32) >= 0)
+               pdata->micdet_delay = val32;
+
+       if (of_property_read_u32_array(np, "gpio-cfg", pdata->gpio_cfg,
+                                      ARRAY_SIZE(pdata->gpio_cfg)) >= 0) {
+               /*
+                * In device tree: 0 means "write 0",
+                * 0xffffffff means "don't touch".
+                *
+                * In platform data: 0 means "don't touch",
+                * 0x8000 means "write 0".
+                *
+                * Note: WM8903_GPIO_CONFIG_ZERO == 0x8000.
+                *
+                *  Convert from DT to pdata representation here,
+                * so no other code needs to change.
+                */
+               for (i = 0; i < ARRAY_SIZE(pdata->gpio_cfg); i++) {
+                       if (pdata->gpio_cfg[i] == 0) {
+                               pdata->gpio_cfg[i] = WM8903_GPIO_CONFIG_ZERO;
+                       } else if (pdata->gpio_cfg[i] == 0xffffffff) {
+                               pdata->gpio_cfg[i] = 0;
+                       } else if (pdata->gpio_cfg[i] > 0x7fff) {
+                               dev_err(&i2c->dev, "Invalid gpio-cfg[%d] %x\n",
+                                       i, pdata->gpio_cfg[i]);
+                               return -EINVAL;
+                       }
+               }
+       }
+
+       return 0;
+}
+
 static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
                                      const struct i2c_device_id *id)
 {
@@ -2111,6 +2154,12 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
                        if (ret != 0)
                                return ret;
                }
+
+               if (i2c->dev.of_node) {
+                       ret = wm8903_set_pdata_from_of(i2c, wm8903->pdata);
+                       if (ret != 0)
+                               return ret;
+               }
        }
 
        ret = regmap_read(wm8903->regmap, WM8903_SW_RESET_AND_ID, &val);