This patch makes it so the wm8903 is initialized from it's device tree node. Signed-off-by: John Bonesio<bones@xxxxxxxxxxxx> --- 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@7000c000 { status = "ok"; clock-frequency = <400000>; + + codec: wm8903@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@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) { -- To unsubscribe from this list: send the line "unsubscribe linux-tegra" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html