imx3的sai3时钟问题

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

imx3的sai3时钟问题

837 Views
CheLL
Contributor III

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

0 Kudos
3 Replies

811 Views
weidong_sun
NXP TechSupport
NXP TechSupport

Hi CheLL,

①目前播放的声音是48000Hz32bit的单声道wav文件,但是BLK的时钟是48000*32*2=3072000Hz

是不是驱动默认都是双声道?

是的,驱动是这么做的。

②用imx8mm的wm8524播放44100Hz16bit的单声道的wav文件,没有出现如下错误

当播放44.1K文件时,driver里切换了PLL,即和48K时用的PLL不一样。

 

因此,你需要好好检查一下底层。

 

weidong

0 Kudos

826 Views
weidong_sun
NXP TechSupport
NXP TechSupport

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

0 Kudos

821 Views
CheLL
Contributor III

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

0 Kudos