• HDA codec相关(1) 基本原理


    转自:https://blog.csdn.net/qq_21186033/article/details/117655677

    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。

     

    本文来自博客园,作者:王楼小子,转载请注明原文链接:https://www.cnblogs.com/wanglouxiaozi/p/15768379.html

  • 相关阅读:
    Python 线程(三):Condition(条件变量)
    Python 线程(二):简单锁实现线程同步
    Python 线程(一):创建线程
    Python 正则表达式
    Python List 、 元组、字典操作
    Python 特殊函数(filter, map, reduce等)
    (一) log4cpp的安装
    (六) 字符和字符串
    (五) 使用DLL函数
    (四) 自定义函数
  • 原文地址:https://www.cnblogs.com/wanglouxiaozi/p/15768379.html
Copyright © 2020-2023  润新知