[alsa-devel] DT soundcard driver with special clock routing
Hi,
I'm developing a DT-based driver for an ARM SoC device with the following special clock routing:
- WM8758 codec attached to the CPU DAI via I2S - the codec is I2S clock master - the CPU feeds the codec with 12MHz clock (outside of the I2S) - the codec converts the 12MHz internally to 48kHz*256 or 44.1kHz *256 clock and provides it to I2S as MCLK
So the special set-up needed here is that the codec needs to be configured to: a) generate the proper MCLK b) enable the respective GPIO pin as clock output
What is the best way of representing this set-up using device tree? I'm wondering if this can be done by adding a specific option in the codec DT binding for enabling the clock output and then use the simple audio card. Or do I need to write a specific soundcard driver that sets up the codec registers? I would like to avoid that if possible and use existing code...
What would you recommend?
Thanks
On 10/12/15 17:31, Petr Kulhavy wrote:
Hi,
I'm developing a DT-based driver for an ARM SoC device with the following special clock routing:
- WM8758 codec attached to the CPU DAI via I2S
- the codec is I2S clock master
- the CPU feeds the codec with 12MHz clock (outside of the I2S)
- the codec converts the 12MHz internally to 48kHz*256 or 44.1kHz *256
clock and provides it to I2S as MCLK
So the special set-up needed here is that the codec needs to be configured to: a) generate the proper MCLK b) enable the respective GPIO pin as clock output
What is the best way of representing this set-up using device tree? I'm wondering if this can be done by adding a specific option in the codec DT binding for enabling the clock output and then use the simple audio card. Or do I need to write a specific soundcard driver that sets up the codec registers? I would like to avoid that if possible and use existing code...
What would you recommend?
I assume when the clock enable/disable code is not there it could be added to the codec driver, e.g. like in case of max98090. The clock source just needs to be exposed as a common clock object.
As an example of similar setup you could take a look at arch/arm/boot/dts/exynos4412-odroid-common.dts. The difference was that in case of Odroid the clock was generated by a PLL inside a SoC, then it was routed to I2S which fed the clock to the codec through the SoC's io pin. The codec was I2S master and the I2S IP block was actually a source of its main ("mclk") clock. I hope this helps.
Hi Sylwester,
thank you for the explanation. I can follow the clock description in the DT and it looks like a reasonable approach. However neither the codec or I2S seem to implement any clock provider. How is the implementation side done? I mean someone needs to set the PLLs, etc.
Thanks Petr
On 10.12.2015 18:13, Sylwester Nawrocki wrote:
On 10/12/15 17:31, Petr Kulhavy wrote:
Hi,
I'm developing a DT-based driver for an ARM SoC device with the following special clock routing:
- WM8758 codec attached to the CPU DAI via I2S
- the codec is I2S clock master
- the CPU feeds the codec with 12MHz clock (outside of the I2S)
- the codec converts the 12MHz internally to 48kHz*256 or 44.1kHz *256
clock and provides it to I2S as MCLK
So the special set-up needed here is that the codec needs to be configured to: a) generate the proper MCLK b) enable the respective GPIO pin as clock output
What is the best way of representing this set-up using device tree? I'm wondering if this can be done by adding a specific option in the codec DT binding for enabling the clock output and then use the simple audio card. Or do I need to write a specific soundcard driver that sets up the codec registers? I would like to avoid that if possible and use existing code...
What would you recommend?
I assume when the clock enable/disable code is not there it could be added to the codec driver, e.g. like in case of max98090. The clock source just needs to be exposed as a common clock object.
As an example of similar setup you could take a look at arch/arm/boot/dts/exynos4412-odroid-common.dts. The difference was that in case of Odroid the clock was generated by a PLL inside a SoC, then it was routed to I2S which fed the clock to the codec through the SoC's io pin. The codec was I2S master and the I2S IP block was actually a source of its main ("mclk") clock. I hope this helps.
Hello Petr,
On 14/12/15 12:32, Petr Kulhavy wrote:
thank you for the explanation. I can follow the clock description in the DT and it looks like a reasonable approach. However neither the codec or I2S seem to implement any clock provider. How is the implementation side done? I mean someone needs to set the PLLs, etc.
Yes, you need the clock provider somewhere. In my case it was the I2S driver that registered a clock provider. Probably you can add your output clock provider to your SoC's main clock controller driver, and perhaps use pinctrl API for the pin function mux setup.
You can place assigned-clock* DT properties in the clock provider node and the PLL's will be configured by the kernel's clk subsystem. Grep for of_clk_set_defaults or see last chapter of Documentation/devicetree/bindings/clock/clock-bindings.txt.
Hi Sylwester,
Currently I'm struggling with the clocks on the DaVinci platform as the clock tree is defined in the platform driver and not in DT. Is there a way to reference the clocks by names from DT, or does the DaVinci clock driver need to be rewritten for DT support?
There is one more thing I came across using the simple soundcard driver. The codec needs to be set to generate the clock via PLL. Unfortunately the simple soundcard always passes clock ID 0 to snd_soc_dai_set_sysclk() - I need a different value for the internal PLL.
What is the preferred approach here? On one hand the simple soundcard driver could be extended with a DT parameter "clock ID". Or does a dedicated soundcard driver need to be written?
Thanks Petr
On 14.12.2015 13:28, Sylwester Nawrocki wrote:
Yes, you need the clock provider somewhere. In my case it was the I2S driver that registered a clock provider. Probably you can add your output clock provider to your SoC's main clock controller driver, and perhaps use pinctrl API for the pin function mux setup. You can place assigned-clock* DT properties in the clock provider node and the PLL's will be configured by the kernel's clk subsystem. Grep for of_clk_set_defaults or see last chapter of Documentation/devicetree/bindings/clock/clock-bindings.txt.
(Adding ASoC maintainer at Cc).
On 16/12/15 08:54, Petr Kulhavy wrote:
Currently I'm struggling with the clocks on the DaVinci platform as the clock tree is defined in the platform driver and not in DT. Is there a way to reference the clocks by names from DT, or does the DaVinci clock driver need to be rewritten for DT support?
I don't think so, you need a clock provider to reference clocks in DT. You may want to ask such question on linux-arm-kernel@lists.infradead.org mailing list and Cc relevant maintainer(s).
There is one more thing I came across using the simple soundcard driver. The codec needs to be set to generate the clock via PLL. Unfortunately the simple soundcard always passes clock ID 0 to snd_soc_dai_set_sysclk() - I need a different value for the internal PLL.
What is the preferred approach here? On one hand the simple soundcard driver could be extended with a DT parameter "clock ID". Or does a dedicated soundcard driver need to be written?
I'm not sure what is the preference here, I guess a dedicated soundcard driver could be a way to go in your case.
On 14.12.2015 13:28, Sylwester Nawrocki wrote:
Yes, you need the clock provider somewhere. In my case it was the I2S driver that registered a clock provider. Probably you can add your output clock provider to your SoC's main clock controller driver, and perhaps use pinctrl API for the pin function mux setup. You can place assigned-clock* DT properties in the clock provider node and the PLL's will be configured by the kernel's clk subsystem. Grep for of_clk_set_defaults or see last chapter of Documentation/devicetree/bindings/clock/clock-bindings.txt.
participants (2)
-
Petr Kulhavy
-
Sylwester Nawrocki