在uda1341的i2s中256fs,384fs和512fs表示的实际意义和如何auto智能选择
连接到uda1341的SYSCLK功能的pin12引脚的供uda1341芯片使用的系统时钟可以有3种[luther.gliethttp]
这对应s3c2410的@CODECLK = 256fs和@CODECLK = 384fs
256fs, 384fs or 512fs system clock frequencies (fsys)
可以看到256fs,384fs和512fs都是一种供codec使用的system clock模式,与实际的音频采样率只是存在一个简单的乘机关系,这就像pll倍频一样,将以音频采样频率为base基数,然后以256,384或512倍频后的频率作为codec芯片的system clock系统驱动时钟[luther.gliethttp].
============================================
下面来自《UDA1341TS.pdf》
7.1 System clock
The UDA1341TS accommodates slave mode only, this
means that in all applications the system devices must
provide the system clock. The system frequency is
selectable. The options are 256fs, 384fs or 512fs.
The system clock must be locked in frequency to the digital
interface signals.
============================================
下面来自《s3c2410.pdf》
Table 21-1. CODEC clock (CODECLK = 256 or 384fs)
IISLRCK 8.000 11.025 16.000 22.050 32.000 44.100 48.000 64.000 88.200 96.000
(fs) kHz kHz kHz kHz kHz kHz kHz kHz kHz kHz
256fs
CODECLK 2.0480 2.8224 4.0960 5.6448 8.1920 11.2896 12.2880 16.3840 22.5792 24.5760
(MHz) 384fs
3.0720 4.2336 6.1440 8.4672 12.2880 16.9344 18.4320 24.5760 33.8688 36.8640
其中8.000*256fs=2.0480M,即为如果s3c2410为codec提供的sysclk系统时钟为256倍频,那么s3c2410的实际
产生的CODECLK时钟频率应为2.0480MHz,同理如果在8k采样率下使用384倍频的codec的sysclk时钟传输模式,
那么需要提供给codec的sysclk为3.0720MHz,其他的类推即可[luther.gliehttp]
s3c24xx_uda134x_startup
for (i = 0; i < 2; i++) {
int fs = i ? 256 : 384;
rates[i*33] = clk_get_rate(xtal) / fs; // 不经过分频的话当前fs对应的rate
for (j = 1; j < 33; j++)
rates[i*33 + j] = clk_get_rate(pclk) / // 对pclk进行以fs为基准,作j*fs的分频,其中j对应s3c24xx_uda134x_hw_params中的分频系数div
(j * fs); // 因为s3c2410的IISPSR的A和B分频系数dvi取值就是0-31,实际使用为1-32[luther.gliethttp]
}
s3c24xx_uda134x_hw_params
err = 999999;
bi = 0;
for (i = 0; i < 2*33; i++) { // 遍历数组rates[]中的所有数值,找到与rate期望速率偏差最小的那个,其索引被存到bi中[luther.gliethttp].
cerr = rates[i] - rate;
if (cerr < 0)
cerr = -cerr;
if (cerr < err) {
err = cerr;
bi = i;
}
}
if (bi / 33 == 1) // 因为rates[0-32]存放的是384fs对应的数据,rates[33-65]存放的是256fs对应的数据,同时从上面的查找算法也可以看到如果384fs和256fs都有符合的,那么最后会使用256fs,因为频率越低,功耗越低,越省电[luther.gliethttp]
fs_mode = S3C2410_IISMOD_256FS;
else
fs_mode = S3C2410_IISMOD_384FS;
if (bi % 33 == 0) {
clk_source = S3C24XX_CLKSRC_MPLL; // ok, 是xtal对应的rates数值,CODECLK时钟由xtal提供[luther.gliethttp]
div = 1;
} else {
clk_source = S3C24XX_CLKSRC_PCLK; // CODECLK时钟由pclk提供
div = bi % 33;
}
snd_soc_dai_set_sysclk会调用dai->ops->set_sysclk(dai, clk_id, freq, dir);
s3c24xx_uda134x_hw_params
snd_soc_dai_set_sysclk(cpu_dai, clk_source , clk, SND_SOC_CLOCK_IN);会调用s3c24xx_i2s_set_sysclk
snd_soc_dai_set_sysclk(codec_dai, 0, clk, SND_SOC_CLOCK_OUT);会调用uda134x_set_dai_sysclk
static int uda134x_set_dai_sysclk(struct snd_soc_dai *codec_dai,
int clk_id, unsigned int freq, int dir)
{
struct snd_soc_codec *codec = codec_dai->codec;
struct uda134x_priv *uda134x = codec->private_data;
pr_debug("%s clk_id: %d, freq: %u, dir: %d\n", __func__,
clk_id, freq, dir);
/* Anything between 256fs*8Khz and 512fs*48Khz should be acceptable
because the codec is slave. Of course limitations of the clock
master (the IIS controller) apply.
We'll error out on set_hw_params if it's not OK */
if ((freq >= (256 * 8000)) && (freq <= (512 * 48000))) {
uda134x->sysclk = freq;
return 0;
}
printk(KERN_ERR "%s unsupported sysclk\n", __func__);
return -EINVAL;
}
阅读(11625) | 评论(1) | 转发(0) |