[RFC 3/3] ARM:Tegra: Device Tree Support: Initialize from wm8903 the device tree
John Bonesio
bones at secretlab.ca
Thu May 12 09:27:18 EST 2011
This patch makes it so the wm8903 is initialized from it's device tree node.
Signed-off-by: John Bonesio<bones at secretlab.ca>
---
arch/arm/boot/dts/tegra-harmony.dts | 17 ++++++
sound/soc/codecs/wm8903.c | 93 +++++++++++++++++++++++++++++++++--
sound/soc/tegra/Kconfig | 2 -
sound/soc/tegra/harmony.c | 8 +++
4 files changed, 115 insertions(+), 5 deletions(-)
diff --git a/arch/arm/boot/dts/tegra-harmony.dts b/arch/arm/boot/dts/tegra-harmony.dts
index af169aa..05521a5 100644
--- a/arch/arm/boot/dts/tegra-harmony.dts
+++ b/arch/arm/boot/dts/tegra-harmony.dts
@@ -19,6 +19,23 @@
i2c at 7000c000 {
status = "ok";
clock-frequency = <400000>;
+
+ codec: wm8903 at 1a {
+ compatible = "wlf,wm8903";
+ reg = <0x1a>;
+ interrupts = < 347 >;
+ irq-active-low = <0>;
+ micdet-cfg = <0>;
+ micdet-delay = <100>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ gpio-base = < 224 >;
+ gpio-num-cfg = < 5 >;
+ /* #define WM8903_GPIO_NO_CONFIG 0x8000 */
+ gpio-cfg = < 0x8000 0x8000 0 0x8000 0x8000 >;
+ };
};
i2c at 7000c400 {
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index f52b623..2347201 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -1865,10 +1865,14 @@ static void wm8903_init_gpio(struct snd_soc_codec *codec)
wm8903->gpio_chip.ngpio = WM8903_NUM_GPIO;
wm8903->gpio_chip.dev = codec->dev;
- if (pdata && pdata->gpio_base)
+ wm8903->gpio_chip.base = -1;
+ if (pdata && pdata->gpio_base) {
wm8903->gpio_chip.base = pdata->gpio_base;
- else
- wm8903->gpio_chip.base = -1;
+ } else if (codec->dev->of_node) {
+ prop = of_get_property(codec->dev->of_node, "gpio-base", NULL);
+ if (prop)
+ wm8903->gpio_chip.base = be32_to_cpup(prop);
+ }
ret = gpiochip_add(&wm8903->gpio_chip);
if (ret != 0)
@@ -1898,6 +1902,11 @@ static int wm8903_probe(struct snd_soc_codec *codec)
{
struct wm8903_platform_data *pdata = dev_get_platdata(codec->dev);
struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
+ const unsigned int *prop;
+ int micdet_cfg = 0;
+ int irq_active_low;
+ int num_gpios = 0;
+ int gpio_cfg = 0;
int ret, i;
int trigger, irq_pol;
u16 val;
@@ -1964,10 +1973,76 @@ static int wm8903_probe(struct snd_soc_codec *codec)
WARN_ON(!mic_gpio && (pdata->micdet_cfg & WM8903_MICDET_ENA));
wm8903->mic_delay = pdata->micdet_delay;
+ } else if (codec->dev->of_node) {
+ bool mic_gpio = false;
+
+ prop = of_get_property(codec->dev->of_node, "gpio-num-cfg", NULL);
+ if (prop)
+ num_gpios = be32_to_cpup(prop);
+
+ prop = of_get_property(codec->dev->of_node, "gpio-cfg", NULL);
+ if (num_gpios && prop) {
+ for (i = 0; i < num_gpios; i++) {
+ gpio_cfg = be32_to_cpu(prop[i]);
+
+ if (gpio_cfg == WM8903_GPIO_NO_CONFIG)
+ continue;
+
+ snd_soc_write(codec, WM8903_GPIO_CONTROL_1 + i,
+ gpio_cfg & 0xffff);
+
+ val = (gpio_cfg & WM8903_GP1_FN_MASK)
+ >> WM8903_GP1_FN_SHIFT;
+
+ switch (val) {
+ case WM8903_GPn_FN_MICBIAS_CURRENT_DETECT:
+ case WM8903_GPn_FN_MICBIAS_SHORT_DETECT:
+ mic_gpio = true;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ prop = of_get_property(codec->dev->of_node, "interrupts", NULL);
+ if (prop)
+ wm8903->irq = be32_to_cpup(prop);
+
+ prop = of_get_property(codec->dev->of_node, "micdet-cfg", NULL);
+ if (prop)
+ micdet_cfg = be32_to_cpup(prop);
+
+ snd_soc_write(codec, WM8903_MIC_BIAS_CONTROL_0, micdet_cfg);
+
+ if (micdet_cfg)
+ snd_soc_update_bits(codec, WM8903_WRITE_SEQUENCER_0,
+ WM8903_WSEQ_ENA, WM8903_WSEQ_ENA);
+
+ /* If microphone detection is enabled in device tree but
+ * detected via IRQ then interrupts can be lost before
+ * the machine driver has set up microphone detection
+ * IRQs as the IRQs are clear on read. The detection
+ * will be enabled when the machine driver configures.
+ */
+ WARN_ON(!mic_gpio && (micdet_cfg & WM8903_MICDET_ENA));
+
+ prop = of_get_property(codec->dev->of_node, "micdet-delay", NULL);
+ if (prop)
+ wm8903->mic_delay = be32_to_cpup(prop);
+
}
if (wm8903->irq) {
- if (pdata && pdata->irq_active_low) {
+ if (pdata) {
+ irq_active_low = pdata->irq_active_low;
+ } else if (codec->dev->of_node) {
+ prop = of_get_property(codec->dev->of_node, "irq-active-low", NULL);
+ if (prop)
+ irq_active_low = be32_to_cpup(prop);
+ }
+
+ if (irq_active_low) {
trigger = IRQF_TRIGGER_LOW;
irq_pol = WM8903_IRQ_POL;
} else {
@@ -2057,6 +2132,16 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8903 = {
};
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+
+#if defined(CONFIG_OF)
+/* Match table for of_platform binding */
+static const struct of_device_id wm8903_of_match[] __devinitconst = {
+ { .compatible = "wlf,wm8903", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, wm8903_of_match);
+#endif
+
static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig
index 66b504f..6dc89bc 100644
--- a/sound/soc/tegra/Kconfig
+++ b/sound/soc/tegra/Kconfig
@@ -16,7 +16,7 @@ config SND_TEGRA_SOC_I2S
config SND_TEGRA_SOC_HARMONY
tristate "SoC Audio support for Tegra Harmony reference board"
- depends on SND_TEGRA_SOC && MACH_HARMONY && I2C
+ depends on SND_TEGRA_SOC && (MACH_HARMONY || MACH_TEGRA_DT) && I2C
default m
select SND_TEGRA_SOC_I2S
select SND_SOC_WM8903
diff --git a/sound/soc/tegra/harmony.c b/sound/soc/tegra/harmony.c
index 556a571..f225087 100644
--- a/sound/soc/tegra/harmony.c
+++ b/sound/soc/tegra/harmony.c
@@ -292,12 +292,20 @@ static __devinit int tegra_snd_harmony_probe(struct platform_device *pdev)
struct snd_soc_card *card = &snd_soc_harmony;
struct tegra_harmony *harmony;
struct harmony_audio_platform_data *pdata;
+ const char *sprop;
int ret;
+#ifdef CONFIG_OF
+ if ((!of_machine_is_compatible("nvidia,harmony")) && (!machine_is_harmony())) {
+ dev_err(&pdev->dev, "Not running on Tegra Harmony!\n");
+ return -ENODEV;
+ }
+#else
if (!machine_is_harmony()) {
dev_err(&pdev->dev, "Not running on Tegra Harmony!\n");
return -ENODEV;
}
+#endif
pdata = pdev->dev.platform_data;
if (!pdata) {
More information about the devicetree-discuss
mailing list