[alsa-devel] [PATCH 4/4] ASoC: adau17x1: Add option to provide platform data via DT
Andreas Irestål
andreas.irestal at axis.com
Tue Feb 2 15:31:50 CET 2016
Signed-off-by: Andreas Irestål <andire at axis.com>
---
.../devicetree/bindings/sound/adi,adau17x1.txt | 33 ++++++
include/dt-bindings/sound/adau17x1.h | 14 +++
sound/soc/codecs/adau1761.c | 131 +++++++++++++++++++++
sound/soc/codecs/adau1781.c | 57 +++++++++
4 files changed, 235 insertions(+)
create mode 100644 include/dt-bindings/sound/adau17x1.h
diff --git a/Documentation/devicetree/bindings/sound/adi,adau17x1.txt b/Documentation/devicetree/bindings/sound/adi,adau17x1.txt
index 90f3ac3..296b417 100644
--- a/Documentation/devicetree/bindings/sound/adi,adau17x1.txt
+++ b/Documentation/devicetree/bindings/sound/adi,adau17x1.txt
@@ -12,10 +12,43 @@ Required properties:
- reg: The i2c address. Value depends on the state of ADDR0
and ADDR1, as wired in hardware.
+Optional properties:
+
+ - input-differential bool to set if the input is differential
+ - digital-microphone bool to set if there is a digital microphone connected
+ to the digmic/jackdet pin.
+ - micbias-vg Microphone bias voltage
+ MICBIAS_0_90_AVDD - 0.9 * AVDD
+ MICBIAS_0_65_AVDD - 0.65 * AVDD
+
+Optional properties (ADAU1361/ADAU1461/ADAU1761/ADAU1961 only)
+
+ - jack-detection If present, configures codec to use the digmic/jackdet
+ pin for jack detection. must provide one of
+ JACKDETECT_ACTIVE_LO or JACKDETECT_ACTIVE_HI followed
+ by debounce time in ms, which must be 5, 10, 20, or 40.
+
+ - lineout-mode Set output mode of the lineout pins.
+ - headphone-mode Set output mode of the headphone pins.
+
+The output mode must be one of:
+ OUTPUT_MODE_HEADPHONE - Headphone output
+ OUTPUT_MODE_HEADPHONE_CAPLESS - Capless headphone output
+ OUTPUT_MODE_LINE - Line output
+
+
+
Example:
+#include <dt-bindings/sound/adau17x1.h>
+
i2c_bus {
adau1361 at 38 {
compatible = "adi,adau1361";
reg = <0x38>;
+ input-differential;
+ jack-detection = <JACKDETECT_ACTIVE_LO 40>;
+ lineout-mode = <OUTPUT_MODE_LINE>;
+ headphone-mode = <OUTPUT_MODE_HEADPHONE>;
+ micbias-vg = <MICBIAS_0_90_AVDD>;
};
};
diff --git a/include/dt-bindings/sound/adau17x1.h b/include/dt-bindings/sound/adau17x1.h
new file mode 100644
index 0000000..3152019
--- /dev/null
+++ b/include/dt-bindings/sound/adau17x1.h
@@ -0,0 +1,14 @@
+#ifndef __DT_ADAU17X1_H
+#define __DT_ADAU17X1_H
+
+#define MICBIAS_0_90_AVDD 0
+#define MICBIAS_0_65_AVDD 1
+
+#define OUTPUT_MODE_HEADPHONE 0
+#define OUTPUT_MODE_HEADPHONE_CAPLESS 1
+#define OUTPUT_MODE_LINE 2
+
+#define JACKDETECT_ACTIVE_HI 0
+#define JACKDETECT_ACTIVE_LO 1
+
+#endif
diff --git a/sound/soc/codecs/adau1761.c b/sound/soc/codecs/adau1761.c
index 16fed36..22106b2 100644
--- a/sound/soc/codecs/adau1761.c
+++ b/sound/soc/codecs/adau1761.c
@@ -18,6 +18,7 @@
#include <sound/soc.h>
#include <sound/tlv.h>
#include <linux/platform_data/adau17x1.h>
+#include <dt-bindings/sound/adau17x1.h>
#include "adau17x1.h"
#include "adau1761.h"
@@ -636,13 +637,143 @@ static bool adau1761_readable_register(struct device *dev, unsigned int reg)
return adau17x1_readable_register(dev, reg);
}
+#ifdef CONFIG_OF
+static inline void adau1761_parse_of_outmode(struct snd_soc_codec *codec,
+ uint32_t of_val,
+ enum adau1761_output_mode *mode)
+{
+ switch (of_val) {
+ case OUTPUT_MODE_HEADPHONE:
+ *mode = ADAU1761_OUTPUT_MODE_HEADPHONE;
+ break;
+ case OUTPUT_MODE_HEADPHONE_CAPLESS:
+ *mode = ADAU1761_OUTPUT_MODE_HEADPHONE_CAPLESS;
+ break;
+ case OUTPUT_MODE_LINE:
+ *mode = ADAU1761_OUTPUT_MODE_LINE;
+ break;
+ default:
+ dev_warn(codec->dev, "Invalid output mode %d\n", of_val);
+ *mode = ADAU1761_OUTPUT_MODE_LINE;
+ break;
+ }
+}
+
+static void adau1761_pdata_from_of(struct snd_soc_codec *codec,
+ struct adau1761_platform_data *pdata)
+{
+ struct device_node *np = codec->dev->of_node;
+ uint32_t val;
+ uint32_t debounce_pars[2];
+
+ if (of_get_property(np, "input-differential", NULL))
+ pdata->input_differential = 1;
+ else
+ pdata->input_differential = 0;
+
+ if (of_get_property(np, "jack-detection", NULL)) {
+ pdata->digmic_jackdetect_pin_mode =
+ ADAU1761_DIGMIC_JACKDET_PIN_MODE_JACKDETECT;
+ if (!of_property_read_u32_array(np, "jack-detection",
+ debounce_pars, 2)) {
+ pdata->jackdetect_active_low =
+ debounce_pars[0] == JACKDETECT_ACTIVE_LO;
+ switch (debounce_pars[1]) {
+ case 5:
+ pdata->jackdetect_debounce_time =
+ ADAU1761_JACKDETECT_DEBOUNCE_5MS;
+ break;
+ case 10:
+ pdata->jackdetect_debounce_time =
+ ADAU1761_JACKDETECT_DEBOUNCE_10MS;
+ break;
+ case 20:
+ pdata->jackdetect_debounce_time =
+ ADAU1761_JACKDETECT_DEBOUNCE_20MS;
+ break;
+ case 40:
+ pdata->jackdetect_debounce_time =
+ ADAU1761_JACKDETECT_DEBOUNCE_40MS;
+ break;
+ default:
+ dev_warn(codec->dev, "Invalid debounce_time %d\n",
+ debounce_pars[1]);
+ pdata->jackdetect_debounce_time =
+ ADAU1761_JACKDETECT_DEBOUNCE_40MS;
+ break;
+ }
+ } else if (!of_property_read_u32_array(np, "jack-detection",
+ debounce_pars, 1)) {
+ dev_warn(codec->dev, "Debounce time not provided\n");
+ pdata->jackdetect_active_low =
+ debounce_pars[0] == JACKDETECT_ACTIVE_LO;
+ } else {
+ dev_warn(codec->dev, "No jack detection settings found\n");
+ pdata->jackdetect_active_low = 0;
+ pdata->jackdetect_debounce_time =
+ ADAU1761_JACKDETECT_DEBOUNCE_40MS;
+ }
+ } else if (of_get_property(np, "digital-microphone", NULL)) {
+ pdata->digmic_jackdetect_pin_mode =
+ ADAU1761_DIGMIC_JACKDET_PIN_MODE_DIGMIC;
+ } else {
+ pdata->digmic_jackdetect_pin_mode =
+ ADAU1761_DIGMIC_JACKDET_PIN_MODE_NONE;
+ }
+
+ if (!of_property_read_u32(np, "headphone-mode", &val))
+ adau1761_parse_of_outmode(codec, val, &pdata->headphone_mode);
+ else
+ pdata->headphone_mode = ADAU1761_OUTPUT_MODE_LINE;
+
+ if (!of_property_read_u32(np, "lineout-mode", &val))
+ adau1761_parse_of_outmode(codec, val, &pdata->lineout_mode);
+ else
+ pdata->lineout_mode = ADAU1761_OUTPUT_MODE_LINE;
+
+ if (!of_property_read_u32(np, "micbias-vg", &val)) {
+ switch (val) {
+ case MICBIAS_0_65_AVDD:
+ pdata->micbias_voltage = ADAU17X1_MICBIAS_0_65_AVDD;
+ break;
+ case MICBIAS_0_90_AVDD:
+ pdata->micbias_voltage = ADAU17X1_MICBIAS_0_90_AVDD;
+ break;
+ default:
+ dev_warn(codec->dev, "Invalid micbias voltage setting\n");
+ pdata->micbias_voltage = ADAU17X1_MICBIAS_0_90_AVDD;
+ break;
+ }
+ } else {
+ pdata->micbias_voltage = ADAU17X1_MICBIAS_0_90_AVDD;
+ }
+}
+#else
+static void adau1761_pdata_from_of(struct snd_soc_codec *codec,
+ struct adau1761_platform_data *pdata)
+{
+}
+#endif
+
static int adau1761_codec_probe(struct snd_soc_codec *codec)
{
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
struct adau1761_platform_data *pdata = codec->dev->platform_data;
struct adau *adau = snd_soc_codec_get_drvdata(codec);
+ struct device_node *np = codec->dev->of_node;
+ struct adau1761_platform_data *of_pdata;
int ret;
+ if (!pdata && np && of_device_is_available(np)) {
+ of_pdata = devm_kzalloc(codec->dev, sizeof(*of_pdata),
+ GFP_KERNEL);
+ if (!of_pdata)
+ return -ENOMEM;
+ adau1761_pdata_from_of(codec, of_pdata);
+ pdata = of_pdata;
+ codec->dev->platform_data = pdata;
+ }
+
ret = adau17x1_add_widgets(codec);
if (ret < 0)
return ret;
diff --git a/sound/soc/codecs/adau1781.c b/sound/soc/codecs/adau1781.c
index bc1bb56..b207911 100644
--- a/sound/soc/codecs/adau1781.c
+++ b/sound/soc/codecs/adau1781.c
@@ -18,6 +18,7 @@
#include <sound/soc.h>
#include <sound/tlv.h>
#include <linux/platform_data/adau17x1.h>
+#include <dt-bindings/sound/adau17x1.h>
#include "adau17x1.h"
#include "adau1781.h"
@@ -380,13 +381,69 @@ static int adau1781_set_input_mode(struct adau *adau, unsigned int reg,
ADAU1781_INPUT_DIFFERNTIAL, val);
}
+#ifdef CONFIG_OF
+static void adau1781_pdata_from_of(struct snd_soc_codec *codec,
+ struct adau1781_platform_data *pdata)
+{
+ struct device_node *np = codec->dev->of_node;
+ uint32_t val;
+
+ if (of_get_property(np, "input-differential", NULL)) {
+ pdata->left_input_differential = 1;
+ pdata->right_input_differential = 1;
+ } else {
+ pdata->left_input_differential = 0;
+ pdata->right_input_differential = 0;
+ }
+
+ if (of_get_property(np, "digital-microphone", NULL))
+ pdata->use_dmic = 1;
+ else
+ pdata->use_dmic = 0;
+
+ if (!of_property_read_u32(np, "micbias-vg", &val)) {
+ switch (val) {
+ case MICBIAS_0_65_AVDD:
+ pdata->micbias_voltage = ADAU17X1_MICBIAS_0_65_AVDD;
+ break;
+ case MICBIAS_0_90_AVDD:
+ pdata->micbias_voltage = ADAU17X1_MICBIAS_0_90_AVDD;
+ break;
+ default:
+ dev_warn(codec->dev, "Invalid micbias voltage setting\n");
+ pdata->micbias_voltage = ADAU17X1_MICBIAS_0_90_AVDD;
+ break;
+ }
+ } else {
+ pdata->micbias_voltage = ADAU17X1_MICBIAS_0_90_AVDD;
+ }
+}
+#else
+static void adau1781_pdata_from_of(struct snd_soc_codec *codec,
+ struct adau1781_platform_data *pdata)
+{
+}
+#endif
+
static int adau1781_codec_probe(struct snd_soc_codec *codec)
{
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
struct adau1781_platform_data *pdata = dev_get_platdata(codec->dev);
struct adau *adau = snd_soc_codec_get_drvdata(codec);
+ struct device_node *np = codec->dev->of_node;
+ struct adau1781_platform_data *of_pdata;
int ret;
+ if (!pdata && np && of_device_is_available(np)) {
+ of_pdata = devm_kzalloc(codec->dev, sizeof(*of_pdata),
+ GFP_KERNEL);
+ if (!of_pdata)
+ return -ENOMEM;
+ adau1781_pdata_from_of(codec, of_pdata);
+ pdata = of_pdata;
+ codec->dev->platform_data = pdata;
+ }
+
ret = adau17x1_add_widgets(codec);
if (ret)
return ret;
--
2.1.4
More information about the Alsa-devel
mailing list