[RFC 3/3] ARM:Tegra: Device Tree Support: Initialize from wm8903 the device tree

Stephen Warren swarren at nvidia.com
Thu May 12 01:01:17 EDT 2011


John Bonesio wrote at Wednesday, May 11, 2011 5:27 PM:
> This patch makes it so the wm8903 is initialized from it's device tree
> node.

> 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>;

Nit: Maybe group all the WM8903-specific fields together, rather than
spacing them out and interleaving the gpio-controller/gpio-cells in the
middle of them?

> +
> +			gpio-controller;
> +			#gpio-cells = <2>;
> +
> +			gpio-base = < 224 >;
> +			gpio-num-cfg = < 5 >;

I don't think gpio-num-cfg is required; the codec always exports 5 GPIOs.

> +			/* #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);
> +	}

The above checks for pdata first, then falls back to of_node. However,
The previous i2c-tegra.c patch checks of_node first then falls back to
pdata. It seems like the ordering should be consistent (although
changing the I2C patch might be best, since I imagine checking pdata
first would lead to least compatibility issues)

> @@ -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);

Again, I'd just hard-code num_gpios==WM8903_NUM_GPIO in the
loop below, instead of making it configurable, since the HW is fixed.

> +		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);
> +

The above chunk duplicates a lot of code in the pdata and of_node paths.

Instead, perhaps it'd be better to do something more like:

if (!pdata && of_node) {
    pdata = kalloc()
    read of_node, convert & write to pdata
}
if (pdata) {
    // existing code to handle pdata
}

That way, the code to handle the pdata is re-used and not duplicated.

> diff --git a/sound/soc/tegra/harmony.c b/sound/soc/tegra/harmony.c
>...
> +#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

Is that backwards-compatible if CONFIG_OF is enabled, but a devicetree
wasn't provided, but instead the old-style Harmony machine ID was used?
I note that the board-harmony.c machine description doesn't include a
DT_MACHINE_START listing that compatible value; only board-dt.c does
this, and that has a different ARM machine ID.

-- 
nvpublic



More information about the linux-arm-kernel mailing list