[alsa-devel] ASoC: sun4i-i2s: Restricting the MCLK
I am using the new sun4i-i2s driver in linux-next to run a sta326 codec via the pin header on a cubietruck (this involves some soldering as described in [1]). The codec can only be configured as slave and needs a master clock for its internal PLL. It is therefore great that, unlike many other SOCs, the a20 provides a MCLK that can be used to sync the codec. However, in my case there is a restriction imposed on the MCLK by the codec. As stated in the datasheet [2], the master clock should be at maximum 12.288 MHz/11.2896 MHz or otherwise the codec will not work (confirmed by experiment!).
Since the mod clock of the a20's dai block is running at twice this frequency, I need to assure that the MLCK divider is at least 2. Actually it is rather straight forward to achieve this by changing the breaking condition in the divider calculation, as shown by the following one-line patch:
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index 687a8f8..8920844 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c @@ -206,7 +206,7 @@ static int sun4i_i2s_set_clk_rate(struct sun4i_i2s *i2s, clk_rate, rate); - if ((bclk_div >= 0) && (mclk_div >= 0)) + if ((bclk_div >= 0) && (mclk_div >= 1)) break; }
Of course, this is just a hack to fix my use case and I am wondering what would be the best way to handle my corner case more generally? I see one option in introducing a DT property mlck_mindiv, or similar, that defaults to 1 and can be overwritten at the board level. I'm willing to prepare a proper patch to tackle this problem but right now I'm wondering if there a major objections to this approach or whether there is any better solution to the problem.
Best regards,
Thomas
[1] https://hifiduino.wordpress.com/2014/03/07/cubieboard-for-audio/ [2] www.st.com/resource/en/datasheet/sta326.pdf
Hi,
On Tue, Aug 2, 2016 at 11:05 PM, Thomas Niederprüm niederp@physik.uni-kl.de wrote:
I am using the new sun4i-i2s driver in linux-next to run a sta326 codec via the pin header on a cubietruck (this involves some soldering as described in [1]). The codec can only be configured as slave and needs a master clock for its internal PLL. It is therefore great that, unlike many other SOCs, the a20 provides a MCLK that can be used to sync the codec. However, in my case there is a restriction imposed on the MCLK by the codec. As stated in the datasheet [2], the master clock should be at maximum 12.288 MHz/11.2896 MHz or otherwise the codec will not work (confirmed by experiment!).
Since the mod clock of the a20's dai block is running at twice this frequency, I need to assure that the MLCK divider is at least 2. Actually it is rather straight forward to achieve this by changing the breaking condition in the divider calculation, as shown by the following one-line patch:
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index 687a8f8..8920844 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c @@ -206,7 +206,7 @@ static int sun4i_i2s_set_clk_rate(struct sun4i_i2s *i2s, clk_rate, rate);
if ((bclk_div >= 0) && (mclk_div >= 0))
if ((bclk_div >= 0) && (mclk_div >= 1)) break; }
Of course, this is just a hack to fix my use case and I am wondering what would be the best way to handle my corner case more generally? I see one option in introducing a DT property mlck_mindiv, or similar, that defaults to 1 and can be overwritten at the board level. I'm willing to prepare a proper patch to tackle this problem but right now I'm wondering if there a major objections to this approach or whether there is any better solution to the problem.
I think the proper way would be to have sun4i-i2s support the .set_sysclk callback in .dai_ops. simple-card calls snd_soc_dai_set_sysclk if you have the "mclk-fs" property set in the DT.
Regards ChenYu
Best regards,
Thomas
[1] https://hifiduino.wordpress.com/2014/03/07/cubieboard-for-audio/ [2] www.st.com/resource/en/datasheet/sta326.pdf _______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
Am Donnerstag, den 04.08.2016, 10:45 +0800 schrieb Chen-Yu Tsai:
Hi,
On Tue, Aug 2, 2016 at 11:05 PM, Thomas Niederprüm niederp@physik.uni-kl.de wrote:
I am using the new sun4i-i2s driver in linux-next to run a sta326 codec via the pin header on a cubietruck (this involves some soldering as described in [1]). The codec can only be configured as slave and needs a master clock for its internal PLL. It is therefore great that, unlike many other SOCs, the a20 provides a MCLK that can be used to sync the codec. However, in my case there is a restriction imposed on the MCLK by the codec. As stated in the datasheet [2], the master clock should be at maximum 12.288 MHz/11.2896 MHz or otherwise the codec will not work (confirmed by experiment!).
Since the mod clock of the a20's dai block is running at twice this frequency, I need to assure that the MLCK divider is at least 2. Actually it is rather straight forward to achieve this by changing the breaking condition in the divider calculation, as shown by the following one-line patch:
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index 687a8f8..8920844 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c @@ -206,7 +206,7 @@ static int sun4i_i2s_set_clk_rate(struct sun4i_i2s *i2s, clk_rate, rate);
- if ((bclk_div >= 0) && (mclk_div >= 0)) + if ((bclk_div >= 0) && (mclk_div >= 1)) break; }
Of course, this is just a hack to fix my use case and I am wondering what would be the best way to handle my corner case more generally? I see one option in introducing a DT property mlck_mindiv, or similar, that defaults to 1 and can be overwritten at the board level. I'm willing to prepare a proper patch to tackle this problem but right now I'm wondering if there a major objections to this approach or whether there is any better solution to the problem.
I think the proper way would be to have sun4i-i2s support the .set_sysclk callback in .dai_ops. simple-card calls snd_soc_dai_set_sysclk if you have the "mclk-fs" property set in the DT.
Thanks for pointing this out. While this indeed seems to be the standard way to obtain control over the mclk and it would probably solve my use case, I see a problem in retaining the current behaviour of the driver if .set_sysclk is implemented. Right now the driver automatically chooses the correct frequency of the mod clock (44.1kHz family or 48kHz family) and the dividers for the mclk and the bclk depending on the requested samplerate. The upside of this that if you are not interested in the mclk, the dai will probably just work for you. The downside is that outside the driver you can not control the mclk.
If .set_sysclk is implemented, the driver has to respect the value set by the function. Thus, the driver can only set the bclk divider according to the predetermined mclk and the requested samplerate. This means that a part of the logic that is currently in the sun4i-i2s driver has to be provided by the layer above. In particular, this means to ensure that the mclk matches the frequency family (44.1kHz or 48kHz) of the requested samplerate and that mclk = 2^n * bclk. As you pointed out the "mclk-fs" property could (partially) do this in the case of simple-card. This would ensure the correct frequency family for the mclk but is not as sophisticated as the current solution in the driver when it comes to choosing the optimal dividers. While the current solution always chooses the highest possible oversampling, the "mclk-fs" solution fixes the oversampling.
The question now boils to whether we want to have external control on the mclk or sophisticated automatic setting of it.
Best regards, Thomas
Regards ChenYu
Best regards,
Thomas
[1] https://hifiduino.wordpress.com/2014/03/07/cubieboard-for-audio/ [2] www.st.com/resource/en/datasheet/sta326.pdf _______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
participants (2)
-
Chen-Yu Tsai
-
Thomas Niederprüm