[alsa-devel] Low sample rates for SGTL5000 on i.MX28
I'm testing the 3.18 kernel for i.MX28 EVK, which has an SGTL5000 CODEC. I notice that audio cannot be output at 8 kHz or 11.025 kHz, although the SGTL5000 data sheet table 8 indicates this should be possible.
If I try to play or record at 8 kHz or 11.025 kHz, I get an error message:
# aplay test_8k.wav [ 6168.910201] mxs_evk_startup: Skipped programming wolfson codec Playing WAVE 'test_8k.wav' : Signed 16 bit Little Endian, Rate 8000 Hz, Mono [ 6168.941211] sgtl5000 0-000a: Invalid mclk frequency: 4.096MHz [ 6168.947047] mxs-sgtl5000 sound.11: ASoC: machine hw_params failed: -22 aplay: set_params:1145: Unable to install hw params: ...
For an 8 kHz sample rate, I get
Invalid mclk frequency: 4.096MHz
For 11.025 kHz sample rate, I get
Invalid mclk frequency: 5.644MHz
Looking in the code (/sound/soc/mxs/mxs-sgtl5000c), I see:
/* Sgtl5000 sysclk should be >= 8MHz and <= 27M */ if (mclk < 8000000 || mclk > 27000000) { dev_err(codec_dai->dev, "Invalid mclk frequency: %u.%03uMHz\n", mclk / 1000000, mclk / 1000 % 1000); return -EINVAL; }
But a sysclk constraint of 8 to 27 MHz only applies if the supplied clock is asynchronous to the frame clock, and the internal clock is being generated by PLL (which it's not in this case). So I tried removing this constraint. But I found that from codecs/sgtl5000.c, I would get the error "PLL not supported in slave mode". I tried changing the switch (sgtl5000->sysclk / sys_fs) to switch (sgtl5000->sysclk / frame_rate), on the basis of the SGTL5000 data sheet table 8. But the resulting audio sounds funny (frequency shifted).
Looking in the SGTL5000 data sheet table 18, it seems unclear whether the MCLK_FREQ field is a multiple of the sample rate (Fs) or the internal system sample rate SYS_FS. It seems that there is some inconsistency in the interpretation of this in codecs/sgtl5000.c compared to mxs/mxs-sgtl5000.c.
What is the correct interpretation of the SGTL5000 data sheet MCLK_FREQ field, and can the mxs-sgtl5000 driver be fixed to support 8 kHz and 11.025 kHz sample rates?
On Thu, Nov 13, 2014 at 4:34 AM, Craig McQueen craig.mcqueen@beamcommunications.com wrote:
I'm testing the 3.18 kernel for i.MX28 EVK, which has an SGTL5000 CODEC. I notice that audio cannot be output at 8 kHz or 11.025 kHz, although the SGTL5000 data sheet table 8 indicates this should be possible.
If I try to play or record at 8 kHz or 11.025 kHz, I get an error message:
# aplay test_8k.wav [ 6168.910201] mxs_evk_startup: Skipped programming wolfson codec
Is this really a mainline kernel? I don't see any 'mxs_evk_startup' in mainline.
Playing WAVE 'test_8k.wav' : Signed 16 bit Little Endian, Rate 8000 Hz,
Mono [ 6168.941211] sgtl5000 0-000a: Invalid mclk frequency: 4.096MHz [ 6168.947047] mxs-sgtl5000 sound.11: ASoC: machine hw_params failed: -22 aplay: set_params:1145: Unable to install hw params: ...
For an 8 kHz sample rate, I get
Invalid mclk frequency: 4.096MHz
I am not able to reproduce this bug here. I can play 8kHz file on the mx28evk:
root@freescale /home$ aplay mono_8k.wav Playing WAVE 'mono_8k.wav' : Unsigned 8 bit, Rate 8000 Hz, Mono
On 13/11/14 23:32, Fabio Estevam wrote:
On Thu, Nov 13, 2014 at 4:34 AM, Craig McQueen craig.mcqueen@beamcommunications.com wrote:
I'm testing the 3.18 kernel for i.MX28 EVK, which has an SGTL5000 CODEC. I notice that audio cannot be output at 8 kHz or 11.025 kHz, although the SGTL5000 data sheet table 8 indicates this should be possible.
If I try to play or record at 8 kHz or 11.025 kHz, I get an error message:
# aplay test_8k.wav [ 6168.910201] mxs_evk_startup: Skipped programming wolfson codec
Is this really a mainline kernel? I don't see any 'mxs_evk_startup' in mainline.
You're right, I cut-and-pasted that from my original work on a custom audio driver on a 3.14 kernel. Sorry about that. But still, I get the same error on the 3.18-rc4 kernel. Here is a sample:
# aplay -D hw:0,0 stereo_8k.wav Playing WAVE 'stereo_8k.wav' : Signed 16 bit Little Endian, Rate 8000 Hz, Stereo [ 3718.857813] sgtl5000 0-000a: Invalid mclk frequency: 4.096MHz [ 3718.865460] mxs-sgtl5000 sound: ASoC: machine hw_params failed: -22 aplay: set_params:1297: Unable to install hw params: ACCESS: RW_INTERLEAVED FORMAT: S16_LE SUBFORMAT: STD SAMPLE_BITS: 16 FRAME_BITS: 32 CHANNELS: 2 RATE: 8000 ...
Playing WAVE 'test_8k.wav' : Signed 16 bit Little Endian, Rate 8000 Hz,
Mono [ 6168.941211] sgtl5000 0-000a: Invalid mclk frequency: 4.096MHz [ 6168.947047] mxs-sgtl5000 sound.11: ASoC: machine hw_params failed: -22 aplay: set_params:1145: Unable to install hw params: ...
For an 8 kHz sample rate, I get
Invalid mclk frequency: 4.096MHz
I am not able to reproduce this bug here. I can play 8kHz file on the mx28evk:
root@freescale /home$ aplay mono_8k.wav Playing WAVE 'mono_8k.wav' : Unsigned 8 bit, Rate 8000 Hz, Mono
If you're playing a mono file successfully, then you must be going through an ALSA plugin that does some sort of rate/format/channel conversion. That depends on what's in asoundrc. Please try it with the -D hw:0,0 parameter and a stereo file.
On Thu, Nov 13, 2014 at 8:36 PM, Craig McQueen craig.mcqueen@beamcommunications.com wrote:
If you're playing a mono file successfully, then you must be going through an ALSA plugin that does some sort of rate/format/channel conversion. That depends on what's in asoundrc. Please try it with the -D hw:0,0 parameter and a stereo file.
That's interesting: I can play your three wav files if I run "aplay file.wav" on mx28evk.
However, if I pass -D hw:0,0 I get different results:
aplay -D hw:0,0 stereo_16k.wav Playing WAVE 'stereo_16k.wav' : Signed 16 bit Little Endian, Rate 16000 Hz, Stereo
also works, but:
root@freescale /home$ aplay -D hw:0,0 stereo_8k.wav Playing WAVE 'stereo_8k.wav' : Signed 16[ 1023.301833] sgtl5000 0-000a: Invalid mclk frequency: 4.096MHz bit Little Endian, Rate[ 1023.309341] mxs-sgtl5000 sound: ASoC: machine hw_para ms failed: -22 8000 Hz, Stereo aplay: set_params:1123: Unable to install hw params: ACCESS: RW_INTERLEAVED FORMAT: S16_LE SUBFORMAT: STD SAMPLE_BITS: 16 FRAME_BITS: 32 CHANNELS: 2 RATE: 8000 PERIOD_TIME: 125000 PERIOD_SIZE: 1000 PERIOD_BYTES: 4000 PERIODS: 4 BUFFER_TIME: 500000 BUFFER_SIZE: 4000 BUFFER_BYTES: 16000 TICK_TIME: 0
Not sure why 'aplay -D hw:0,0 stereo_8k.wav' works and 'aplay stereo_8k.wav' succeeds.
On Thu, Nov 13, 2014 at 9:34 PM, Fabio Estevam festevam@gmail.com wrote:
On Thu, Nov 13, 2014 at 8:36 PM, Craig McQueen craig.mcqueen@beamcommunications.com wrote:
If you're playing a mono file successfully, then you must be going through an ALSA plugin that does some sort of rate/format/channel conversion. That depends on what's in asoundrc. Please try it with the -D hw:0,0 parameter and a stereo file.
That's interesting: I can play your three wav files if I run "aplay file.wav" on mx28evk.
However, if I pass -D hw:0,0 I get different results:
aplay -D hw:0,0 stereo_16k.wav Playing WAVE 'stereo_16k.wav' : Signed 16 bit Little Endian, Rate 16000 Hz, Stereo
also works, but:
root@freescale /home$ aplay -D hw:0,0 stereo_8k.wav Playing WAVE 'stereo_8k.wav' : Signed 16[ 1023.301833] sgtl5000 0-000a: Invalid mclk frequency: 4.096MHz bit Little Endian, Rate[ 1023.309341] mxs-sgtl5000 sound: ASoC: machine hw_para ms failed: -22 8000 Hz, Stereo aplay: set_params:1123: Unable to install hw params: ACCESS: RW_INTERLEAVED FORMAT: S16_LE SUBFORMAT: STD SAMPLE_BITS: 16 FRAME_BITS: 32 CHANNELS: 2 RATE: 8000 PERIOD_TIME: 125000 PERIOD_SIZE: 1000 PERIOD_BYTES: 4000 PERIODS: 4 BUFFER_TIME: 500000 BUFFER_SIZE: 4000 BUFFER_BYTES: 16000 TICK_TIME: 0
Not sure why 'aplay -D hw:0,0 stereo_8k.wav' works and 'aplay stereo_8k.wav' succeeds.
Ok, so the 'aplay stereo_8k.wav' is converting the rate to 44.1kHz, so that's why it does not fail.
On Thu, Nov 13, 2014 at 10:29 PM, Fabio Estevam festevam@gmail.com wrote:
Ok, so the 'aplay stereo_8k.wav' is converting the rate to 44.1kHz, so that's why it does not fail.
From the sgtl5000 datasheet, it looks like the MCLK range of 8 to
27MHz limitation does not apply when sgtl5000 runs in slave mode.
A quick hack that allows 'aplay -D hw:0,0 stereo_8k.wav' to play:
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 6bb77d7..4a329b0 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -623,13 +623,6 @@ static int sgtl5000_set_clock(struct snd_soc_codec *codec, if (sgtl5000->master) { clk_ctl |= SGTL5000_MCLK_FREQ_PLL << diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 6bb77d7..4a329b0 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -623,13 +623,6 @@ static int sgtl5000_set_clock(struct snd_soc_codec *codec, if (sgtl5000->master) { clk_ctl |= SGTL5000_MCLK_FREQ_PLL << SGTL5000_MCLK_FREQ_SHIFT; - } else { - dev_err(codec->dev, - "PLL not supported in slave mode\n"); - dev_err(codec->dev, "%d ratio is not supported. " - "SYS_MCLK needs to be 256, 384 or 512 * fs\n", - sgtl5000->sysclk / sys_fs); - return -EINVAL; } }
@@ -1417,7 +1410,6 @@ static int sgtl5000_i2c_probe(struct i2c_client *client, { struct sgtl5000_priv *sgtl5000; int ret, reg, rev; - unsigned int mclk;
sgtl5000 = devm_kzalloc(&client->dev, sizeof(struct sgtl5000_priv), GFP_KERNEL); @@ -1441,14 +1433,6 @@ static int sgtl5000_i2c_probe(struct i2c_client *client, return ret; }
- /* SGTL5000 SYS_MCLK should be between 8 and 27 MHz */ - mclk = clk_get_rate(sgtl5000->mclk); - if (mclk < 8000000 || mclk > 27000000) { - dev_err(&client->dev, "Invalid SYS_CLK frequency: %u.%03uMHz\n", - mclk / 1000000, mclk / 1000 % 1000); - return -EINVAL; - } - ret = clk_prepare_enable(sgtl5000->mclk); if (ret) return ret; diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c index 61822cc..3bba6cf 100644 --- a/sound/soc/mxs/mxs-sgtl5000.c +++ b/sound/soc/mxs/mxs-sgtl5000.c @@ -49,13 +49,6 @@ static int mxs_sgtl5000_hw_params(struct snd_pcm_substream *s break; }
- /* Sgtl5000 sysclk should be >= 8MHz and <= 27M */ - if (mclk < 8000000 || mclk > 27000000) { - dev_err(codec_dai->dev, "Invalid mclk frequency: %u.%03uMHz\n", - mclk / 1000000, mclk / 1000 % 1000); - return -EINVAL; - } - /* Set SGTL5000's SYSCLK (provided by SAIF MCLK) */ ret = snd_soc_dai_set_sysclk(codec_dai, SGTL5000_SYSCLK, mclk, 0); if (ret) {
On Thu, Nov 13, 2014 at 10:59 PM, Fabio Estevam festevam@gmail.com wrote:
On Thu, Nov 13, 2014 at 10:29 PM, Fabio Estevam festevam@gmail.com wrote:
Ok, so the 'aplay stereo_8k.wav' is converting the rate to 44.1kHz, so that's why it does not fail.
From the sgtl5000 datasheet, it looks like the MCLK range of 8 to 27MHz limitation does not apply when sgtl5000 runs in slave mode.
A quick hack that allows 'aplay -D hw:0,0 stereo_8k.wav' to play:
I don't have a scope handy to measure the MCLK, LRCLK, but I found a bug below where we use sys_fs instead of frame_rate:
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 6bb77d7..a46ec7e 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -605,7 +605,7 @@ static int sgtl5000_set_clock(struct snd_soc_codec *codec, int frame_rate) * calculate the divider of mclk/sample_freq, * factor of freq =96k can only be 256, since mclk in range (12m,27m) */ - switch (sgtl5000->sysclk / sys_fs) { + switch (sgtl5000->sysclk / frame_rate) { case 256: clk_ctl |= SGTL5000_MCLK_FREQ_256FS << SGTL5000_MCLK_FREQ_SHIFT; @@ -1441,14 +1441,6 @@ static int sgtl5000_i2c_probe(struct i2c_client *client, return ret; }
- /* SGTL5000 SYS_MCLK should be between 8 and 27 MHz */ - mclk = clk_get_rate(sgtl5000->mclk); - if (mclk < 8000000 || mclk > 27000000) { - dev_err(&client->dev, "Invalid SYS_CLK frequency: %u.%03uMHz\n", - mclk / 1000000, mclk / 1000 % 1000); - return -EINVAL; - } - ret = clk_prepare_enable(sgtl5000->mclk); if (ret) return ret; diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c index 61822cc..3bba6cf 100644 --- a/sound/soc/mxs/mxs-sgtl5000.c +++ b/sound/soc/mxs/mxs-sgtl5000.c @@ -49,13 +49,6 @@ static int mxs_sgtl5000_hw_params(struct snd_pcm_substream *substream, break; }
- /* Sgtl5000 sysclk should be >= 8MHz and <= 27M */ - if (mclk < 8000000 || mclk > 27000000) { - dev_err(codec_dai->dev, "Invalid mclk frequency: %u.%03uMHz\n", - mclk / 1000000, mclk / 1000 % 1000); - return -EINVAL; - } - /* Set SGTL5000's SYSCLK (provided by SAIF MCLK) */ ret = snd_soc_dai_set_sysclk(codec_dai, SGTL5000_SYSCLK, mclk, 0); if (ret) {
aplay -D hw:0,0 /home/stereo_8k.wav plays in a incorrect pitch, so we still need to adjust the clocking.
participants (2)
-
Craig McQueen
-
Fabio Estevam