We continue to allow the AB8500 CODEC to be registered via the AB8500
Multi Functional Device API, only this time we extract its configuration
from the Device Tree binary.

Signed-off-by: Lee Jones <lee.jo...@linaro.org>
---
 include/linux/mfd/abx500/ab8500-codec.h |    6 ++-
 sound/soc/codecs/ab8500-codec.c         |   81 +++++++++++++++++++++++++++++++
 2 files changed, 85 insertions(+), 2 deletions(-)

diff --git a/include/linux/mfd/abx500/ab8500-codec.h 
b/include/linux/mfd/abx500/ab8500-codec.h
index dc65292..d707941 100644
--- a/include/linux/mfd/abx500/ab8500-codec.h
+++ b/include/linux/mfd/abx500/ab8500-codec.h
@@ -23,7 +23,8 @@ enum amic_type {
 /* Mic-biases */
 enum amic_micbias {
        AMIC_MICBIAS_VAMIC1,
-       AMIC_MICBIAS_VAMIC2
+       AMIC_MICBIAS_VAMIC2,
+       AMIC_MICBIAS_UNKNOWN
 };
 
 /* Bias-voltage */
@@ -31,7 +32,8 @@ enum ear_cm_voltage {
        EAR_CMV_0_95V,
        EAR_CMV_1_10V,
        EAR_CMV_1_27V,
-       EAR_CMV_1_58V
+       EAR_CMV_1_58V,
+       EAR_CMV_UNKNOWN
 };
 
 /* Analog microphone settings */
diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c
index 23b4018..fa80961 100644
--- a/sound/soc/codecs/ab8500-codec.c
+++ b/sound/soc/codecs/ab8500-codec.c
@@ -34,6 +34,7 @@
 #include <linux/mfd/abx500/ab8500-sysctrl.h>
 #include <linux/mfd/abx500/ab8500-codec.h>
 #include <linux/regulator/consumer.h>
+#include <linux/of.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -2394,9 +2395,65 @@ struct snd_soc_dai_driver ab8500_codec_dai[] = {
        }
 };
 
+static void ab8500_codec_of_probe(struct device *dev, struct device_node *np,
+                               struct ab8500_codec_platform_data *codec)
+{
+       u32 value;
+
+       if (of_get_property(np, "stericsson,amic1-type-single-ended", NULL))
+               codec->amics.mic1_type = AMIC_TYPE_SINGLE_ENDED;
+       else
+               codec->amics.mic1_type = AMIC_TYPE_DIFFERENTIAL;
+
+       if (of_get_property(np, "stericsson,amic2-type-single-ended", NULL))
+               codec->amics.mic2_type = AMIC_TYPE_SINGLE_ENDED;
+       else
+               codec->amics.mic2_type = AMIC_TYPE_DIFFERENTIAL;
+
+       /* Has a non-standard Vamic been requested? */
+       if (of_get_property(np, "stericsson,amic1a-bias-vamic2", NULL))
+               codec->amics.mic1a_micbias = AMIC_MICBIAS_VAMIC2;
+       else
+               codec->amics.mic1a_micbias = AMIC_MICBIAS_VAMIC1;
+
+       if (of_get_property(np, "stericsson,amic1b-bias-vamic2", NULL))
+               codec->amics.mic1b_micbias = AMIC_MICBIAS_VAMIC2;
+       else
+               codec->amics.mic1b_micbias = AMIC_MICBIAS_VAMIC1;
+
+       if (of_get_property(np, "stericsson,amic2-bias-vamic1", NULL))
+               codec->amics.mic2_micbias = AMIC_MICBIAS_VAMIC1;
+       else
+               codec->amics.mic2_micbias = AMIC_MICBIAS_VAMIC2;
+
+       if (!of_property_read_u32(np, "stericsson,earpeice-cmv", &value)) {
+               switch (value) {
+               case 950 :
+                       codec->ear_cmv = EAR_CMV_0_95V;
+                       break;
+               case 1100 :
+                       codec->ear_cmv = EAR_CMV_1_10V;
+                       break;
+               case 1270 :
+                       codec->ear_cmv = EAR_CMV_1_27V;
+                       break;
+               case 1580 :
+                       codec->ear_cmv = EAR_CMV_1_58V;
+                       break;
+               default :
+                       codec->ear_cmv = EAR_CMV_UNKNOWN;
+                       dev_err(dev, "Unsuitable earpiece voltage found in 
DT\n");
+               }
+       } else {
+               dev_warn(dev, "No earpiece voltage found in DT - using 
default\n");
+               codec->ear_cmv = EAR_CMV_0_95V;
+       }
+}
+
 static int ab8500_codec_probe(struct snd_soc_codec *codec)
 {
        struct device *dev = codec->dev;
+       struct device_node *np = dev->of_node;
        struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(dev);
        struct ab8500_platform_data *pdata;
        struct filter_control *fc;
@@ -2407,6 +2464,30 @@ static int ab8500_codec_probe(struct snd_soc_codec 
*codec)
        /* Setup AB8500 according to board-settings */
        pdata = (struct ab8500_platform_data *)dev_get_platdata(dev->parent);
 
+       if (np) {
+               if (!pdata)
+                       pdata = devm_kzalloc(dev,
+                                       sizeof(struct ab8500_platform_data),
+                                       GFP_KERNEL);
+
+               if (!pdata->codec)
+                       pdata->codec
+                               = devm_kzalloc(dev,
+                                       sizeof(struct 
ab8500_codec_platform_data),
+                                       GFP_KERNEL);
+
+               if (!(pdata && pdata->codec))
+                       return -ENOMEM;
+
+               ab8500_codec_of_probe(dev, np, pdata->codec);
+
+       } else {
+               if (!(pdata && pdata->codec)) {
+                       dev_err(dev, "No codec platform data or DT found\n");
+                       return -EINVAL;
+               }
+       }
+
        /* Inform SoC Core that we have our own I/O arrangements. */
        codec->control_data = (void *)true;
 
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to