Machine
以装配有CS4270的1款android 智能电视为例
/sound/soc/samsung/exynos.c
Platform
以Samsung cpu exynos4412为例
/sound/soc/samsung/
Codec
以wolfson的Codec芯片cs4270为例
/sound/soc/codecs/cs4270.c
ALSA 框架介绍
Alsa 太多太杂,很难整理的规整,只能看到哪里写到哪里
ASoC被分为Machine,Platform和Codec3大部件,Platform驱动的主要作用是完成音频数据的管理,终究通过CPU的数字音频接口(DAI)把音频数据传送
给Codec进行处理,终究由Codec输出驱动耳机或是喇叭的音信信号。在具体实现上,ASoC有把Platform驱动分为两个部份:snd_soc_platform_driver
和snd_soc_dai_driver。其中,platform_driver负责管理音频数据,把音频数据通过dma或其他操作传送至cpu dai中,dai_driver则主要完成cpu 1侧的
dai的参数配置,同时也会通过1定的途径把必要的dma等参数与snd_soc_platform_driver进行交互。
Machine 是指某1款机器,可以是某款装备,某款开发板,又或是某款智能手机,由此可以看出Machine几近是不可重用的,每一个Machine上的硬件实
现可能都不1样,CPU不1样,Codec不1样,音频的输入、输出装备也不1样,Machine为CPU、Codec、输入输出装备提供了1个载体。
Platform 1般是指某1个SoC平台,比如pxaxxx,s3cxxxx,omapxxx等等,与音频相干的通常包括该SoC中的时钟、DMA、I2S、PCM等等,只要指定了SoC,那么我们可以认为它会有1个对应的Platform,它只与SoC相干,与
Machine无关,这样我们就能够把Platform抽象出来,使得同1款SoC不用做任何的改动,就能够用在不同的Machine中。实际上,把Platform认为是某个SoC更好理解。
Codec 字面上的意思就是编解码器,Codec里面包括了I2S接口、D/A、A/D、Mixer、PA(功放),通常包括多种输入(Mic、Line-in、I2S、PCM)和多个
输出(耳机、喇叭、听筒,Line-out),Codec和Platform 1样,是可重用的部件,同1个Codec可以被不同的Machine使用。嵌入式Codec通常通过I2C对
内部的寄存器进行控制。
Machine驱动的初始化,codec和dai的注册,都会调用snd_soc_instantiate_cards()进行1次声卡和codec,dai,platform的匹配绑定进程,这里所说的
绑定,正如Machine驱动1文中所描写,就是通过3个全局链表,按名字进行匹配,把匹配的codec,dai和platform实例赋值给声卡每对dai的snd_soc_pcm_runtime变量中。1旦绑定成功,将会使得codec和dai驱动的probe回调被调用。alsa架构的数据交互,是通过对PCM装备的操作来完成的, PCM装备分成playback和capture两个stream, 每一个stream底下有N个substream
alsa驱动最底层需要调试的有3块: DMA部份,IIS驱动部份,codec部份



A)I2S有4根线,
1.串行时钟SCLK,也叫位时钟(BCLK),即对应数字音频的每位数据,SCLK都有1个脉冲。SCLK的频率=2×采样频率×采样位数。
2. 帧时钟LRCK,(也称WS),用于切换左右声道的数据。LRCK为“1”表示正在传输的是右声道的数据,为“0”则表示正在传输的是左声道的数据。LRCK
的频率等于采样频率。
3.串行数据SDATA,就是用2进制补码表示的音频数据。
4.有时为了使系统间能够更好地同步,还需要另外传输1个信号MCLK,称为主时钟,也叫系统时钟(Sys Clock),是采样频率的256倍或384倍。
B)声音数据DAT 1般在CLK的上升沿进行采样,有些DAC也是可以调的。每一个声道里面可以容纳的CLK数必须多于数据的位数,多出来的时钟和数据DAC会丢弃不用,比如16bit采样的声音数据当1个声道是32个CLK且left-justify的时候,后面106个时钟的数据会被DAC丢掉,不影响的。
C)I2S数据的格式分I2S, Left-justify, Right-justify。3种格式的区分在于声音数据与WS的对应关系:
1 . I2S模式DAT的MSB在WS变化后的第2个上升沿开始传输
2. Left-justify模式DAT的MSB在WS变化后的第1个上升沿开始传输
3. Right-justify模式DAT的LSB在WS行将变换到下1声道前的最后1个时钟传输
I2S部份触及的几个频率:
* 输出采样频率 fs = 44.1KHz. (也有其它fs的音源, 但加了resampler后, 都变成44.1KHz输出了). 这是个关键频率.
* LRCLK, 就等于fs. (L/R声道信号)
* BCLK = 32倍fs = 1411.2KHz = 1.4112MHz. (bit clock). 2声道16bit, 故32倍fs. 若2声道24bit, 则48倍fs.
* MCLK是全部audio模块的工作频率, 通常选fs的256, 384, 512倍. 比如: 256倍fs = 11289.6KHz = 11.2896MHz.
从频率设置来讲, MCLK是个主要频率, 它是全部audio模块的工作频率.
那末, 从软件来讲要设置两个方面的寄存器: 1是该PLL从晶振频率如何得到PLLout频率(比如P/M/S/k). 2是PLLout如何分频得到audio部份的MCLK.
IIS驱动部份最重要的就是注册以下钩子函数,挂到了alsa驱动上
static const struct snd_soc_dai_ops samsung_i2s_dai_ops = {
.trigger = i2s_trigger,
.hw_params = i2s_hw_params,
.set_fmt = i2s_set_fmt,
.set_clkdiv = i2s_set_clkdiv,
.set_sysclk = i2s_set_sysclk,
.startup = i2s_startup,
.shutdown = i2s_shutdown,
.delay = i2s_delay,
};
codec芯片介绍
cs4270的驱动要设置的参数有:
静音,传输模式,比特位长度,时钟主从模式,音量大小
cs4270驱动里面定义了snd_soc_dai_driver结构成员,里面定义了playback和capture两个substream,同时也挂了1个snd_soc_dai_ops结构体,里面全是操作函数指针。
alsa上面1层层的终究会调用到这些指针
static const struct snd_soc_dai_ops cs4270_dai_ops = {
.hw_params = cs4270_hw_params,
.set_sysclk = cs4270_set_dai_sysclk,
.set_fmt = cs4270_set_dai_fmt,
.digital_mute = cs4270_dai_mute,
};
static struct snd_soc_dai_driver cs4270_dai = {
.name = "cs4270-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_CONTINUOUS,
.rate_min = 4000,
.rate_max = 216000,
.formats = CS4270_FORMATS,
},
.capture = {
.stream_name = "Capture",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_CONTINUOUS,
.rate_min = 4000,
.rate_max = 216000, .
formats = CS4270_FORMATS,
},
.ops = &cs4270_dai_ops,
};
DMA介绍
IIS总线是慢速总线,相对CPU来讲,太慢。所以采取DMA的方式最能节省CPU性能。
PCM playback的时候,DMA目的地址是IIS FIFO寄存器。源地址是寄存PCM数据的内存。
DMA的驱动采取了linux pl330的驱动架构,采取中断的方式来触发后续DMA。
IIS中通过DMA的方式写入FIFO寄存器,在DMA的驱动中挂接了1个回调函数audio_buffdone。DMA完成后,回函数调用,刷新alsa的环,便于下1次DMA
DMA的目的地址,就是IIS发送寄存器的地址。源地址,就是申请的DMA buffer,只不过DMAbuffer被映照成了1个环
static void dma_enqueue(struct snd_pcm_substream *substream)
{
struct runtime_data *prtd = substream->runtime->private_data;
dma_addr_t pos = prtd->dma_pos;
unsigned int limit;
struct samsung_dma_prep dma_info;
pr_debug("Entered %s\n", __func__);
limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period;
pr_debug("%s: loaded %d, limit %d\n", __func__, prtd->dma_loaded, limit);
dma_info.cap = (samsung_dma_has_circular() ? DMA_CYCLIC : DMA_SLAVE);
dma_info.direction = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM);
dma_info.fp = audio_buffdone; //回调函数
dma_info.fp_param = substream;
dma_info.period = prtd->dma_period;
dma_info.len = prtd->dma_period*limit;
while (prtd->dma_loaded < limit) {
pr_debug("dma_loaded: %d\n", prtd->dma_loaded);
if ((pos + dma_info.period) > prtd->dma_end) {
dma_info.period = prtd->dma_end - pos;
pr_debug("%s: corrected dma len %ld\n", __func__, dma_info.period);
}
dma_info.buf = pos;
prtd->params->ops->prepare(prtd->params->ch, &dma_info); //DMA注册
prtd->dma_loaded++;
pos += prtd->dma_period;
if (pos >= prtd->dma_end) pos = prtd->dma_start;
}
prtd->dma_pos = pos;
}
static void audio_buffdone(void *data)
{
struct snd_pcm_substream *substream = data;
struct runtime_data *prtd = substream->runtime->private_data;
pr_debug("Entered %s\n", __func__);
if (prtd->state & ST_RUNNING) {
prtd->dma_pos += prtd->dma_period;
if (prtd->dma_pos >= prtd->dma_end)
prtd->dma_pos = prtd->dma_start;
if (substream)
snd_pcm_period_elapsed(substream);
spin_lock(&prtd->lock);
if (!samsung_dma_has_circular()) {
prtd->dma_loaded--;
dma_enqueue(substream);
} spin_unlock(&prtd->lock);
}
}
DMA部份主要通过注册以下钩子函数来挂到alsa驱动里面
static struct snd_pcm_ops dma_ops = {
.open = dma_open,
.close = dma_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = dma_hw_params,
.hw_free = dma_hw_free,
.prepare = dma_prepare,
.trigger = dma_trigger,
.pointer = dma_pointer,
.mmap = dma_mmap,
};
alsa数据读写简介
A/CC寄存haokan.ct1905.info/Article/1109-49739690.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-99024780.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-94917533.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-93823088.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-45548408.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-85993209.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-18341819.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-69954087.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-31562342.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-29609305.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-29865591.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-71012254.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-73579217.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-22712305.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-48011185.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-15202018.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-99377135.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-99768984.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-19766540.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-15081357.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-19052252.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-72087699.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-18623307.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-64615808.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-20592212.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-19069371.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-27586004.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-12866927.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-26533916.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-45025226.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-71011432.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-88754623.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-93873637.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-45719676.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-02613596.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-52658468.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-18078825.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-01042881.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-34088527.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-00970108.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-71996418.HtmK/k++后续
A/CC寄存haokan.ct1905.info/Article/1109-99362566.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-00331502.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-40634281.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-29210314.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-34905793.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-04194107.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-99024432.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-31491420.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-36549327.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-52058657.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-37061407.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-27736954.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-72096376.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-71650738.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-77313387.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-89217238.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-16944244.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-15092123.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-60513335.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-29719125.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-05778543.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-22574401.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-85123033.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-67478897.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-01094193.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-75630456.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-93949224.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-04964397.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-77208077.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-42137772.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-41685359.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-29057282.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-30699641.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-99620444.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-07069470.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-71344143.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-18729139.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-98553589.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-70138246.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-53565021.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-42549863.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-52043095.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-34998675.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-69051167.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-64355999.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-94484380.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-29650901.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-82725675.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-58370588.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-26798589.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-78155689.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-97227169.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-82046862.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-63921875.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-52592432.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-18382301.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-86694118.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-29432789.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-34183293.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-15298190.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-38016722.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-04049606.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-25946362.HtmK/k++后续
A/CC寄存haokan.wh1847.info/Article/1109-37215607.HtmK/k++后续
A/CC寄存haokan.wh1847.info/A

最低0.47元/天 解锁文章
9715

被折叠的 条评论
为什么被折叠?



