1 基本概念
HDA Codec结构将不同的codec functions描述成一系列参数化模块。每个模块(以及模块的组合)为一个addressable node,每个node都可通过一系列只读的capabilities(parameters)和一系列可读写的command(controls)来进行配置和操作。
Function Group分为Audio Function Group和Modem Function Group,function group中的节点又称为widget。每个widget都有一个独立的地址,用来对它进行控制(controls)或读取widget状态。
每个codec在初始化过程中都会被分配一个独立的codec address(CAd)。codec中的每个节点都有一个独立的node ID(NID)。CAd和NID的结合能够为每个codec中的每个节点组合成一个独立的地址。
每个widget只能属于一个function group,且只能和同一个function group的widget连接;每个Widget都有一系列标准的parameters(capabilities)和controls(命令和状态寄存器)
PCM是英文Pulse-code modulation的缩写, PCM就是要把声音从模拟转换成数字信号的一种技术,他的原理简单地说就是利用一个固定的频率对模拟信号进行采样,采样后的信号在波形上看就像一串连续的幅值不一的脉冲,把这些脉冲的幅值按一定的精度进行量化,这些量化后的数值被连续地输出、传输、处理或记录到存储介质中,所有这些组成了数字音频的产生过程。
此Capabilitie(PCM信号)的重要参数包括的两个重要指标:采样频率和量化精度。
播放音乐时,应用程序从存储介质中读取音频数据(MP3、WMA、AAC......),经过解码后,得到PCM数据,最终送到音频驱动程序中。
在录音时,音频驱动不停地把采样所得的PCM数据送回给应用程序,由应用程序完成压缩、存储等任务。
2 Audio Function Group分类
Audio Output Converter, 主要为DAC或S/PDIF OUT,节点的输入端连接至codec中的HDA link Audio Input Converter, 主要为ADC或者S/PDIF IN,节点的输出端连接至codec中的HDA link
Pin complex widget, 提供了Audio Function Group和其他Function Group的外部连接。HDMI或DP这样的可以操作声音的digital display connection,被归类为digital pin widget。
Mixer, 混合器,在该种节点中,所有输入端必须有相同的放大器参数(若没有则必须全部没有),若需要不同的输入端有不同的放大器参数,则利用multiplexer来连接不同的输入,再连接至mixer中。mixer的所有输入均为硬连接,不能选择只使用其中几个,上面的那几种节点可以。
Multiplexer, 多选器,对input的选择依赖于一个connection selector来完成。
Power Widget,通过对任意widgets的组合提供电源状态控制,来优化电源管理,与其他widget没有硬件上的连接,但是会通过connection list来规定用来控制哪些widget。
Volume Knob Widget,对特定的输出pin提供机械上的音量控制。该widget的connection list描述了哪些widget(主要是pin widget)的音量会被该widget控制。
3 HDA初始化及codec的枚举
(1)控制器初始化
当HDA控制器在上电后,退出上电复位时,所有控制器寄存器将处于其上电默认状态,并且链接将处于非活动状态。启动控制器的第一步是正确编程PCI PCI Express或其他系统总线接口。由于此操作特定于控制器实现,因此应遵循特定控制器的文档。编程结束时,控制器应准备好在系统总线上传输数据。例如,当使用PCI时,中断线 基址和其他PCI配置空间寄存器应正确编程。
当控制器第一次启动时,Offset 08h: GCTL – Global Control寄存器CRST位为0,表示控制器处于复位状态。将CRST位置一来复位HDA控制器,控制器将经历一系列必要的步骤,以使自己脱离复位。链接被启动,状态机将自己初始化。
当硬件执行这些步骤时,CRST位将显示为0。初始化完成后,CRST位的读取将返回1,表示控制器现在已准备好工作。因此,在控制器退出复位后,软件应等待CRST被读取为1后再继续。
(2) codec枚举
当通过CRST启用链路时,codec将检测到重置信号的反断言,并请求控制器进行状态更改和枚举。当控制器硬件检测到这些请求时,它将向codec提供它们的唯一地址,并设置控制器STATESTS位,以指示在相应的SDATA\u INx信号上检测到状态更改事件。软件可以使用这些位来确定连接到链接的codec的地址。给定位位置的1表示存在相关地址处的codec。
例如,值05h意味着有地址为0和2的codec连接到链接。从RESET#de断言到codec请求枚举最晚可长达25帧。在将CRST读取为1之后,软件必须等待至少521us(25帧),然后再假设codec已发出所有状态更改请求并已由控制器注册。这使codec有足够的时间执行自我初始化。
如果软件希望在连接新的codec时获得中断,例如在热插拔事件期间,软件可以将INTCTL寄存器中的CIE位设置为1,以启用包括状态更改事件的控制器中断。当接收到中断时,可以检查STATESTS位,以确定先前未识别的codec是否请求状态更改。
4 HDA与codec通信机制
一旦枚举了附加的codec,就可以向codec发送命令以确定其功能。codec命令和控制描述了向codec发送控制信息和从codec接收控制信息的机制。命令和控制数据是低带宽的异步数据,在链路上一次传输一个命令。无论是控制器的入站还是控制器的出站,都不能以任何方式确保定时。codec命令和控制由控制器通过两个关键机制来处理,即命令出站环形缓冲区(CORB)和响应输入环形缓冲区(RIRB)。软件负责通过CORB控制和RIRB控制寄存器配置控制器的CORB和RIRB。
HDA控制器和codec的通信机制主要依赖于两个机制:
CORB(Command Outbound Ring Buffer)和RIRB(Response Input Ring Buffer)。软件通过CORB和RIRB相关寄存器们来对这两个机制进行配置。
(1)PIO方式
1)将verb数据写入Offset 60h: Immediate Command Output Interface寄存器中。
2)设置Offset 68h: Immediate Command Status寄存器的低俩位置1。
3)查看Offset 68h: Immediate Command Status寄存器的BIT0,确认数据写入执行完毕。
4)从Offset 64h: Immediate Response Input Interface寄存器中将结果读出来。
(2)DMA方式
1)Command Outbound Ring Buffer – CORB
a 数据交互
controller 用来发从命令给codec的机制。CORB是一个系统内存中的环形缓冲区,用于将软件中发送的命令传递给连接在HDA链路上的codecs。另外有两个硬件中的指针,Write Pointer和Read Pointer。写指针是软件用来告诉硬件CORB中最后一个有效的命令是哪个。而硬件通过读指针来告诉软件最后一个获取的命令是哪个。(每向CORB中放入一个新命令,写指针+1(软件写),硬件每处理一个CORB中的命令,读指针+1(硬件写))。HDA控制器中的DMA engine会不停的比较读写指针,当两者不相同时,会不停的从buffer中获取命令通过链路传递到codec上,直到读写指针的值相同。
注:
b Each entry in the CORB is also 32 bits long and matches the verb format.
c first commands will be placed at a offset of 4 bytes into the CORB buffer, as CORBWP will be 0, so CORBWP + 1 will indicate a 4-byte offset into the CORB.
2)Response Inbound Ring Buffer - RIRB
a RIRB数据交互
RIRB是codecs发送回复给controller的机制。同样也是系统内存中的一个环形缓冲区,用来存储连接在链路上的codec发送的response信息。回复可分为请求的(回复controller发送的命令)和自发的(codec直接发送,标记某些事件的)。软件需要区分回复是来自哪个codec的,以及该回复是自发的还是请求的。同CORB相同,RIRB中也有Read Pointer和Write Pointer。读指针仅被软件所使用,用来记录上一个从buffer中读到的回复。写指针在硬件中用来指明最后一个写进buffer中的回复。controller可通过Interrupt和Polling两种方式来通知软件RIRB需要被读了。
b Entry Format
The response passed from the codecs to the controller is 32 bits long. Each entry in the RIRB is 64 bits long.
5 HDA codec数据流
硬件框架如下图:
Streams and Channels
HDA中通过抽象出streams和channels来描述link中传输的数据的方式。
stream是在系统内存和该数据的codec译码时创建的虚拟连接,由通过链路的单个DMA通道驱动。软件负责创建和管理流。与流相关的关键参数,如流参数、通道数、数据格式、位深度等,由软件定义。
channels就是我们很熟悉的声道的概念,所以,一个立体音stream中包含L和R两个channel。
上图描述了上面提到的各个概念之间的关系。每个active stream必须连接到一个DMA引擎上,上面的stream 1,2,3都是active stream,其中1,3是output类型的 stream,2是input类型的stream.4就是一个inactive stream.
下图描述了link、stream、channels之间的关系。
下图描述了Link上数据流帧的格式:
注:Link上传输多个frames,每个frams的大小是固定的
CORB、RIRB是用来传输命令的,对应的数据的传输是通过BDL(Buffer Descriptor List)来管理的。BDL是由BDLE(Buffer Descriptor List Entries)组成的,BDL和BDLE的格式分别如下图:
其中IOC(Interrupt on Completion),这个标志位决定着DMA传输一定数据后触发中断,中断处理中会唤醒应用层阻塞式的写数据线程。这个”一定数据量”其实就是我们在设置hw_params时设置的periods值,periods也就是我们将一大块输出缓存进行了均分出来的的一片片buffer。