mfd: arizona: Add micdet ranges and polarity device tree bindings
authorCharles Keepax <ckeepax@opensource.wolfsonmicro.com>
Thu, 19 Sep 2013 17:01:37 +0000 (18:01 +0100)
committerSeung-Woo Kim <sw0312.kim@samsung.com>
Wed, 14 Dec 2016 04:42:46 +0000 (13:42 +0900)
Add device tree bindings for the pdata that configures the microphone
button detection and microphone detection polarity configurations.

Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
[k.kozlowski: rebased on 4.1, no signed-off-by of previous committer]
Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Documentation/devicetree/bindings/mfd/arizona.txt
drivers/mfd/arizona-core.c

index 9fc9ab4..7c88653 100644 (file)
@@ -43,11 +43,21 @@ Optional properties:
   - wlf,reset : GPIO specifier for the GPIO controlling /RESET
   - wlf,ldoena : GPIO specifier for the GPIO controlling LDOENA
 
-  - wlf,gpio-defaults : A list of GPIO configuration register values. Defines
-    for the appropriate values can found in <dt-bindings/mfd/arizona.txt>. If
-    absent, no configuration of these registers is performed. If any entry has
-    a value that is out of range for a 16 bit register then the chip default
-    will be used. If present exactly five values must be specified.
+
+  - wlf,micd-ranges : Microphone detection level and key configuration, this
+    field can be of variable length but should always be a multiple of 2 cells
+    long, each two cell group represents one button configuration
+    The first cell is the maximum impedance for this button in ohms
+    The second cell the key that should be reported to the input layer
+  - wlf,micd-configs : Headset polarity configurations, the field can be of
+    variable length but should always be a multiple of 3 cells long, each two
+    cell group represents one polarity configration
+    The first cell is the accessory detection source as per the ACCDET_SRC bits
+    in the ACCESSORY_DETECT_MODE_1 register
+    The second cell represents the MICBIAS to be used as per the MICD_BIAS_SRC
+    bits in the MIC_DETECT_1 register
+    The third cell represents the value of the micd-pol-gpio pin, a non-zero
+    value indicates this should be on
 
   - wlf,inmode : A list of INn_MODE register values, where n is the number
     of input signals. Valid values are 0 (Differential), 1 (Single-ended) and
@@ -90,6 +100,19 @@ codec: wm5102@1a {
 
        wlf,gpsw = <0x3>;
 
+       wlf,micd-ranges = <
+               11 0x100
+               28 0x101
+               54 0x102
+               100 0x103
+               186 0x104
+               430 0x105
+       >;
+       wlf,micd-configs = <
+               0x1 1 0
+               0x0 2 1
+       >;
+
        wlf,gpio-defaults = <
                ARIZONA_GP_FN_TXLRCLK
                ARIZONA_GP_DEFAULT
index 6523903..e6d2092 100644 (file)
@@ -519,6 +519,119 @@ int arizona_of_get_named_gpio(struct arizona *arizona, const char *prop,
 }
 EXPORT_SYMBOL_GPL(arizona_of_get_named_gpio);
 
+static int arizona_of_get_u32_num_groups(struct arizona *arizona,
+                                       const char *prop,
+                                       int group_size)
+{
+       int len_prop;
+       int num_groups;
+
+       if (!of_get_property(arizona->dev->of_node, prop, &len_prop))
+               return -EINVAL;
+
+       num_groups =  len_prop / (group_size * sizeof(u32));
+
+       if (num_groups * group_size * sizeof(u32) != len_prop) {
+               dev_err(arizona->dev,
+                       "DT property %s is malformed: %d\n",
+                       prop, -EOVERFLOW);
+               return -EOVERFLOW;
+       }
+
+       return num_groups;
+}
+
+static int arizona_of_get_micd_ranges(struct arizona *arizona,
+                                     const char *prop)
+{
+       int nranges;
+       int i, j;
+       int ret = 0;
+       u32 value;
+       struct arizona_micd_range *micd_ranges;
+
+       nranges = arizona_of_get_u32_num_groups(arizona, prop, 2);
+       if (nranges < 0)
+               return nranges;
+
+       micd_ranges = devm_kzalloc(arizona->dev,
+                                  nranges * sizeof(struct arizona_micd_range),
+                                  GFP_KERNEL);
+
+       for (i = 0, j = 0; i < nranges; ++i) {
+               ret = of_property_read_u32_index(arizona->dev->of_node,
+                                                prop, j++, &value);
+               if (ret < 0)
+                       goto error;
+               micd_ranges[i].max = value;
+
+               ret = of_property_read_u32_index(arizona->dev->of_node,
+                                                prop, j++, &value);
+               if (ret < 0)
+                       goto error;
+               micd_ranges[i].key = value;
+       }
+
+       arizona->pdata.micd_ranges = micd_ranges;
+       arizona->pdata.num_micd_ranges = nranges;
+
+       return ret;
+
+error:
+       devm_kfree(arizona->dev, micd_ranges);
+       dev_err(arizona->dev, "DT property %s is malformed: %d\n", prop, ret);
+       return ret;
+}
+
+static int arizona_of_get_micd_configs(struct arizona *arizona,
+                                      const char *prop)
+{
+       int nconfigs;
+       int i, j;
+       int ret = 0;
+       u32 value;
+       struct arizona_micd_config *micd_configs;
+
+       nconfigs = arizona_of_get_u32_num_groups(arizona, prop, 3);
+       if (nconfigs < 0)
+               return nconfigs;
+
+       micd_configs = devm_kzalloc(arizona->dev,
+                                   nconfigs *
+                                   sizeof(struct arizona_micd_config),
+                                   GFP_KERNEL);
+
+       for (i = 0, j = 0; i < nconfigs; ++i) {
+               ret = of_property_read_u32_index(arizona->dev->of_node,
+                                                prop, j++, &value);
+               if (ret < 0)
+                       goto error;
+               micd_configs[i].src = value;
+
+               ret = of_property_read_u32_index(arizona->dev->of_node,
+                                                prop, j++, &value);
+               if (ret < 0)
+                       goto error;
+               micd_configs[i].bias = value;
+
+               ret = of_property_read_u32_index(arizona->dev->of_node,
+                                                prop, j++, &value);
+               if (ret < 0)
+                       goto error;
+               micd_configs[i].gpio = value;
+       }
+
+       arizona->pdata.micd_configs = micd_configs;
+       arizona->pdata.num_micd_configs = nconfigs;
+
+       return ret;
+
+error:
+       devm_kfree(arizona->dev, micd_configs);
+       dev_err(arizona->dev, "DT property %s is malformed: %d\n", prop, ret);
+       return ret;
+}
+
 static int arizona_of_get_core_pdata(struct arizona *arizona)
 {
        struct arizona_pdata *pdata = &arizona->pdata;
@@ -530,6 +643,9 @@ static int arizona_of_get_core_pdata(struct arizona *arizona)
 
        pdata->reset = arizona_of_get_named_gpio(arizona, "wlf,reset", true);
 
+       arizona_of_get_micd_ranges(arizona, "wlf,micd-ranges");
+       arizona_of_get_micd_configs(arizona, "wlf,micd-configs");
+
        ret = of_property_read_u32_array(arizona->dev->of_node,
                                         "wlf,gpio-defaults",
                                         arizona->pdata.gpio_defaults,