DSP

uda1341ts驱动流程:

2019-07-13 18:31发布

uda1341ts驱动流程:   说明:1、以platform设备驱动形式写              2uda1341ts的驱动程序由两部分组成,在向内核注册的时候分别注册以下两个设备:                    ①用于声音录制和回放的sound设备/dsp设备                  ②用于控制声音的mixer设备              3、在全局变量中定义了,两个 audio_stream_t 结构的变量,分别是output_stream 和 input_stream,一个作为输出音频缓冲区,一个作为输入音频缓冲区。 将输出音频缓冲区的 DMA 通道设为通道 2,输入音频缓冲区的 DMA 通道设为通道 1。   硬件连接方案    语音驱动芯片UDA1341TS和微控制器S3C2410X的连接如图2所示。       S3C2410XIIS总线信号与UDA1341TSIIS信号直接相连。L3接口的引脚L3CLOCKL3MODEL3DATA分别连接到S3C2410XGPBlGPB2GPB3通用数据输出引脚。UDA1341TS对外提供两组音频信号输入接口,每组包括左右2个声道。由于IIS总线只处理音频数据,因此UDA1341TS还内置了用于传输控制信号的L3总线接口。L3接口相当于混音器控制接口,可以控制输入/输出音频信号的低音及音量大小等。L3接口接在S3C2410X3个通用GPIO输入/输出引脚上,利用这3IO口模拟L3总线的全部时序和协议。这里一定要注意L3总线的时钟不是连续时钟,它只在数据线上有数据时才发出8个周期的时钟信号,其他情况下时钟线始终保持高电平。        (一)在设备列表中(mach-s3c2410.c文件中)增加头文件以及uda1341ts的硬件信息  #include #include static struct s3c24xx_uda134x_platform_datas3c24xx_uda134x_data = {         .l3_clk = S3C2410_GPB(4),        .l3_data = S3C2410_GPB(3),        .l3_mode = S3C2410_GPB(2),        .model = UDA134X_UDA1341, };   //根据电路图,L3总线与gpio端口对应   static struct platform_devices3c24xx_uda134x = {        .name = "s3c24xx_uda134x",        .dev = {                 .platform_data =&s3c24xx_uda134x_data,        } }; static struct platform_device*smdk2440_devices[] __initdata = {          ...........         &s3c24xx_uda134x, //uda }   ()probeuda1341ts驱动程序)分析: 主要实现:获得平台资源->申请内存区域-io内存重映射->获得并使能时钟->设置gpio->初始化iis总线->初始化uda1341->audio dma初始化->注册dspmixer->释放内存区域。 1、设置gpio:(1)根据uda1341tsL3总线(L3clockL3dataL3mode)与gpio连接而设置;             2)根据uda1341tsi2s总线(I2SsdiI2SlrckI2SsclkCDCLKI2Ssdo)与gpio连接而设置; 2、初始化iis总线:init_s3c2410_iis_bus() 3、初始化uda1341init_uda1341() 4audio dma初始化(1audio_init_dma(&input_stream,"UDA1341 in")                   2audio_init_dma(&output_stream,"UDA1341 out") 5、注册dspmixer:(1audio_dev_dsp= register_sound_dsp(&smdk2410_audio_fops, -1);                   2audio_dev_mixer= register_sound_mixer(&smdk2410_mixer_fops, -1);   ()remove分析: 禁用时钟->取消dspmixer注册->清除dma 1、取消dspmixer注册:(1unregister_sound_dsp(audio_dev_dsp);                       2unregister_sound_mixer(audio_dev_mixer); 2清除dmaaudio_clear_dma(&output_stream,&s3c2410iis_dma_out);          audio_clear_dma(&input_stream,&s3c2410iis_dma_in);   ()底层的audiomixer其实就是字符设备,完成各自的file_operations结构体后在uda1341ts驱动的probe函数中注册 1audio设备:   (1write函数:判断打开标志是否可写->判断BUFFER内存空间是否可用->判断阻塞方式还是非阻塞方式->循环写入内存块,并将写好的内存块加入dma队列->返回传输字节数x        s3c2410_dma_enqueue函数:发起一次dma传输;在其前面填满了一块内存(即填满一块内存就交给dma去处理)       (2read函数:判断buffer内存空间是否为空,若未空则设置buffer空间,并将buffer内存块放入dma队列->循环将内存块数据读入用户空间->返回读出字节数      ①      (3)open函数:判断设备是否正忙->设置相关参数->初始化iis总线->清除缓冲区         ①初始化iis总线、清除缓冲区:从 file->f_mode中判断文件是否可读可写,根据设备文件的打开模式,分别调用了 init_s3c2410_iis_bus_txinit_s3c2410_iis_bus_rx函数来进行对 IIS总线读写的初始化配置,在这两个函数中对 S3C2410芯片的 IIS相关寄存器进行了相应的配置,会在后面说明。然后又调用了 audio_clear_buf函数来分别对音频输入和输出两个 DMA缓冲区进行了清空,该函数也会在后面说明。因为读写操作控制必须用 f_mode来进行判断,所以这里要根据 f_mode为可读或可写的标识来进行读写模式的硬件设置。而 readwrite函数不需要检查 f_mode因为读写权限的检查是由内核在调用他们之前进行的。   注意:audio_setup_buf函数:是在读写函数中调用audio_setup_buf建立dma内存空间(读为in通道建立,写为out通道建立):   2mixer设备:主要有(openioctlrelease),其中openrelease为空函数  ioctl主要实现的是:声音的控制;            ()uda1341的初始化:设置gpio->uda1341复位->uda1341设置 1、设置gpio:根据uda1341tsL3总线(L3clockL3dataL3mode)与gpio连接而设置; 2uda1341复位/设置:都是通过寄存器赋值完成;    说明:通过设置gpio,则可以使L3mod输出高电平或者低电平,当为低电平的时候,则选择了地址模式,(地址模式是用于选择一个设备为了随后的数据传输和定义目的寄存器,)从而可以通过L3总线中的L3data线找到对应的寄存器,然后使L3mod为高电平,即数据模式,然后通过L3data数据线给前面找到的寄存器赋值   (1)uda1341_l3_address(u8 data)函数:其为地址模式,写入地址(即寻找对应的寄存器)          时序为:时序为L3MODE置电平->L3CLOCK置高电平->L3CLOCK置低电平->写一位地址->延时->L3CLOCK置高电平->L3CLOCK置低电平,开始写地址下一位->...8位地址写完->L3MODEL3CLOCK置高电平   (2)uda1341_l3_data(u8 data)函数:其为数据模式,写入数据(即为寄存器赋值)          时序为:时序为 L3CLOCK置低电平->写一位数据->延时->L3CLOCK置高电平->L3CLOCK置低电平,开始写下一位数据->...8位数据写完,向之前写入的地址地址,一次写数据完成