Hi Everyone:
调试codec芯片
按照下面设备节点播放48000HZ32bit的wav格式没有问题
&sai3 {
assigned-clock-rates = <24576000>;
fsl,sai-asynchronous;
};
但是按照下面节点播放44100Hz16bit的数据遇到如下错误
&sai3 {
assigned-clock-rates = <22579200>;
fsl,sai-asynchronous;
};
错误如下:
evk_8mm:/ # tinyplay /system/vendor/firmware/t
test_44100_16bit.wav test_48000_32bit.wav
inyplay /system/vendor/firmware/test_44100_16bit.wav <
[ 142.987713] aw8838_startup: enter
[ 142.997243] aw8838_startup: enter
[ 143.002116] aw8838_set_fmt: fmt=0x4001
[ 143.005895] lv.t aw8838_get_mclk_rate rate=44100 hz
[ 143.010802] imx-aw8838 sound-aw8838: lv.t imx_aif_hw_params mclk_freq=1411200 hz
[ 143.019388] aw8838_hw_params: requested rate: 44100, sample size: 16
[ 143.027289] aw8838_hw_params: width = 16
[ 143.032795] fsl-sai 30030000.sai: ratio 0 for freq 1411200Hz based on clock 1404343Hz
[ 143.040667] fsl-sai 30030000.sai: sai->verid.id=769
[ 143.045594] fsl-sai 30030000.sai: ret=1404343
[ 143.049996] fsl-sai 30030000.sai: failed to derive required Tx rate: 1411200
[ 143.057270] fsl-sai 30030000.sai: ASoC: can't set 30030000.sai hw params: -22
[ 143.064498] aw8838_mute: mute state=1
Unable to open PCM device 0 (cannot set hw params: Invalid argument)
evk_8mm:/ #
很奇怪这个1404343Hz是从哪来的?是由哪个函数传过去的?
错误函数如下:
static int fsl_sai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq)
{
struct fsl_sai *sai = snd_soc_dai_get_drvdata(dai);
unsigned char offset = sai->soc->reg_offset;
unsigned long clk_rate;
unsigned int reg = 0;
u32 ratio, savesub = freq, saveratio = 0, savediv = 0;
u32 id;
int ret = 0;
/* Don't apply to slave mode */
if (sai->slave_mode[tx])
return 0;
fsl_sai_check_ver(dai);
for (id = 0; id < FSL_SAI_MCLK_MAX; id++) {
clk_rate = clk_get_rate(sai->mclk_clk[id]);
if (!clk_rate)
continue;
ratio = clk_rate / freq;
ret = clk_rate - ratio * freq;
dev_err(dai->dev, "ratio %d for freq %dHz based on clock %ldHz\n",
ratio, freq, clk_rate);
dev_err(dai->dev, "sai->verid.id=%d\n", sai->verid.id);
dev_err(dai->dev, "ret=%d\n", ret);
/*
* Drop the source that can not be
* divided into the required rate.
*/
if (ret != 0 && clk_rate / ret < 1000)
continue;
dev_dbg(dai->dev,
"ratio %d for freq %dHz based on clock %ldHz\n",
ratio, freq, clk_rate);
if ((ratio % 2 == 0 && ratio >= 2 && ratio <= 512) ||
(ratio == 1 && sai->verid.id >= FSL_SAI_VERID_0301)) {
if (ret < savesub) {
saveratio = ratio;
sai->mclk_id[tx] = id;
savesub = ret;
}
if (ret == 0)
break;
}
}
if (saveratio == 0) {
dev_err(dai->dev, "failed to derive required %cx rate: %d\n",
tx ? 'T' : 'R', freq);
return -EINVAL;
}
还有Machine的代码有如下一个函数,params_rate(params);的作用是什么?返回值是传到什么地方的
static unsigned long aw8838_get_mclk_rate(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
//struct snd_soc_pcm_runtime *rtd = substream->private_data;
//struct imx_priv *data = snd_soc_card_get_drvdata(rtd->card);
unsigned int rate = params_rate(params);
int i;
printk( "lv.t aw8838_get_mclk_rate rate=%d hz\n", rate);
/* Find the appropriate MCLK freq */
for (i = 0; i < ARRAY_SIZE(fs_mul); i++) {
if (rate >= fs_mul[i].min && rate <= fs_mul[i].max)
return rate * fs_mul[i].mul;
}
/* Let DAI manage MCLK frequency by default */
return 0;
}
请各位大佬看下,帮忙解答下
万分感谢
Best Wishes
CheLL
Hi CheLL,
①目前播放的声音是48000Hz32bit的单声道wav文件,但是BLK的时钟是48000*32*2=3072000Hz
是不是驱动默认都是双声道?
是的,驱动是这么做的。
②用imx8mm的wm8524播放44100Hz16bit的单声道的wav文件,没有出现如下错误
当播放44.1K文件时,driver里切换了PLL,即和48K时用的PLL不一样。
因此,你需要好好检查一下底层。
weidong
Hello CheLL,
1. 24.576MHz 时钟是48K的整数倍,而22.5792MHz是44.1K的整数倍。
2. 配置为24.576MHz时,没有发生错误提示,是因为24.576MHz的源PLL输出是24.576MHz的整数倍。或者说,这个PLL输出支持这样的频点。
同样的,当你配置MCLK为22.5792MHz时,软件去配置PLL时,无法配置对应的频点,所以sai driver提示有错误。
3. 24.576MHz或者你配置的22.5792MHz,都是要为CODEC提供工作时钟MCLK,这个MCLK在codec内部有2个路径:
(1)直接成为bitclock和LRCLK的源时钟,比如48K采样时,就可以。
(2)这个MCLK进入到codec内部的PLL,输出一个与bitclok/LRCLK相配的时钟。
通常(2)的情况比较多,因为使用PLL可以比较容易地输出需要的时钟,而直接使用MCLK,只能倍频或者分频。
4. 关于谁做Master和谁做Slave的问题
SAI工作在I2S模式时,双方需要分工:一方做Master,提供bitclock / LRCLK;另一方做Slave(被动接收master过来的bitclock/LRCLK)
5. 计算时钟
(1)LRCLK=48K
如果sample rate是48K,16bit 量化,立体声输出,那么播放时,时钟关系是这样的:
Bitclock = 48000 x 16 x2 = 1.536MHz
(2)LRCLK=44.1K
类似地,当LRCLK = 44.1K时:
Bitclock = 441000 x 16 x2 = 1.4112MHz
【注】
对于您使用的android系统来说,上层全部使用44.1K的采用频率,这是android层负责转换sample rate,你完全不需要把MCLK换成22.5792MHz,
目前codec driver底层已经调试好了,因此最好的方式是把android应用层audio调到可以使用。
Hope above information is helpful to you.
Have a nice day!
B.R,
Weidong
Hi weidong_sun:
感谢您的回答
①目前播放的声音是48000Hz32bit的单声道wav文件,但是BLK的时钟是48000*32*2=3072000Hz
是不是驱动默认都是双声道?
②用imx8mm的wm8524播放44100Hz16bit的单声道的wav文件,没有出现如下错误
[ 143.049996] fsl-sai 30030000.sai: failed to derive required Tx rate: 1411200
[ 143.057270] fsl-sai 30030000.sai: ASoC: can't set 30030000.sai hw params: -22
这是什么原因呢?
Hope your answers
Best Wishes
CheLL