tlvaic3101音频芯片开发笔记调试技巧

</pre><pre name="code" class="html">        tlvaic3101音频芯片开发笔记调试技巧
        
4、解读芯片寄存器设置
TLV320AIC3101IRHBT寄存器共分两组:page0和page1,每页127个寄存器, 我们需要关心的主要是page0的127个寄存器
page0中寄存器,按照功能分类如下:
page选择:    register 0
复位:           register 1
配置采样率: register 2 3 4 5 6 7 11
配置数据格式: register 8 9 10
录音ADC音量增益: register 15 16
输入通道设置: regisert 17 ~ 35
输出通道设置: register 37 ~89
输出音量设置:register 43 44
时钟设置:       register 101 102


5、调试音频时,需要注意的地方
调试放音时,
a,放音音量默认设置为最大
b,cpu输出的i2s数据,位宽等要与音频芯片中的设置对等
c,注意通道的选择,硬件上连接的通道与软件寄存器设置的通道要对的上
调试录音时,
a,录音的增益调至最大
b,录音时,mic部分不能有悬空的引脚,否则会出现杂音的。


6、调试技巧
IIC调试
a,可以尝试向音量控制寄存器写入音量,在读出,若都ok的话,则证明iic通讯异常
录音/放音有杂音,放音无声音
a,用逻辑分析仪测试I2S总线,在放音时左声道,右声道的数据应该是一致的,否则需要检查reg10的设置与处理器输出数据设置的关系
b,录音时,测试I2S总线,录音的左右声道数据也应该是一致的,可与手册中的I2S波形进行对比,查找原因。


分析过程:
在\dvrrdk_04.00.00.03.kernel\sound\soc\codecs\tlv320aic3x.c
//重要的数据结构
/* machine i2c codec control layer */
static struct i2c_driver aic3x_i2c_driver = {
	.driver = {
		.name = "tlv320aic3x-codec",
		.owner = THIS_MODULE,
	},
	.probe	= aic3x_i2c_probe,
	.remove = aic3x_i2c_remove,
	.id_table = aic3x_i2c_id,
};


static struct snd_soc_codec_driver soc_codec_dev_aic3x = {
	.set_bias_level = aic3x_set_bias_level,
	.reg_cache_size = ARRAY_SIZE(aic3x_reg),
	.reg_word_size = sizeof(u8),
	.reg_cache_default = aic3x_reg,
	.probe = aic3x_probe,       //声卡的探测和初始化
	.remove = aic3x_remove,     //声卡卸载
	.suspend = aic3x_suspend,   //声卡休眠
	.resume = aic3x_resume,     //声卡从休眠到恢复
};



static struct snd_soc_dai_ops aic3x_dai_ops = {
	.hw_params	= aic3x_hw_params,              //硬件参数设定
	.digital_mute	= aic3x_mute,               //静音操作
	.set_sysclk	= aic3x_set_dai_sysclk,         //系统时钟
	.set_fmt	= aic3x_set_dai_fmt,            //格式设置
};

static struct snd_soc_dai_driver aic3x_dai = {
	.name = "tlv320aic3x-hifi",
	.playback = {
		.stream_name = "Playback",
		.channels_min = 1,
		.channels_max = 2,
		.rates = AIC3X_RATES,
		.formats = AIC3X_FORMATS,},
	.capture = {
		.stream_name = "Capture",
		.channels_min = 1,
		.channels_max = 2,
		.rates = AIC3X_RATES,
		.formats = AIC3X_FORMATS,},
	.ops = &aic3x_dai_ops,      //声卡操作函数集合全部与硬件操作有关
	.symmetric_rates = 1,
};
/




module_init(aic3x_modinit)
    --->aic3x_modinit(void)
            --->i2c_add_driver(&aic3x_i2c_driver)
                    --->aic3x_i2c_probe
                            ---snd_soc_register_codec(&i2c->dev,&soc_codec_dev_aic3x, &aic3x_dai, 1);
                                    //执行结构体中soc_codec_dev_aic3x中的硬件探测函数aic3x_probe
                                    --->aic3x_probe(struct snd_soc_codec *codec)
                                            //硬件寄存器初始化
                                            --->aic3x_init(codec)   
                                            //Output stage volumes控制      
                                            --->snd_soc_add_controls(codec, aic3x_snd_controls,ARRAY_SIZE(aic3x_snd_controls));    
  
  
  
  
  
  
  
在\dvrrdk_04.00.00.03.kernel\sound\soc\soc-core.c
//重要的数据结构,可以参考图来理解由上而下
/* ASoC platform driver */
static struct platform_driver soc_driver = {
	.driver		= {
		.name		= "soc-audio",
		.owner		= THIS_MODULE,
		.pm		= &soc_pm_ops,
	},
	.probe		= soc_probe,
	.remove		= soc_remove,
};



/* ASoC PCM operations */
static struct snd_pcm_ops soc_pcm_ops = {
	.open		= soc_pcm_open,
	.close		= soc_codec_close,
	.hw_params	= soc_pcm_hw_params,
	.hw_free	= soc_pcm_hw_free,
	.prepare	= soc_pcm_prepare,
	.trigger	= soc_pcm_trigger,
	.pointer	= soc_pcm_pointer,
};


static int __init snd_soc_init(void)
                        //platform注册
                    --->platform_driver_register(&soc_driver);
                                 /* probes a new socdev */
                             --->soc_probe(struct platform_device *pdev)
                                    //获取platform设备指针
                                    --->platform_get_drvdata(pdev)
                                        //snd_soc_register_card - Register a card with the ASoC core
                                    --->snd_soc_register_card(card)
                                                --->snd_soc_instantiate_cards();
                                                        --->snd_soc_instantiate_card(card);
                                                                    --->INIT_WORK(&card->deferred_resume_work, soc_resume_deferred);
                                                                    --->soc_probe_dai_link(card, i);
                                                                            /* probe the cpu_dai */
	                                                                        --->if (!cpu_dai->probed) 
	                                                                           /* probe the CODEC */
	                                                                        --->if (!codec->probed) 
	                                                                            /* probe the platform */
	                                                                        --->if (!platform->probed) 
	                                                                            /* probe the CODEC DAI */
	                                                                        --->if (!codec_dai->probed)   
                                                                                //创建一个pcm实例
                                                                            --->soc_new_pcm(rtd, num);
                                                                                    --->snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops);




问1:在tlvaic310x.c中aic3x_mute静音操作函数如何被上层调用的?
答1:  
在
static struct snd_soc_dai_ops aic3x_dai_ops = {
	.hw_params	= aic3x_hw_params,
	.digital_mute	= aic3x_mute,
	.set_sysclk	= aic3x_set_dai_sysclk,
	.set_fmt	= aic3x_set_dai_fmt,
}; 

.digital_mute
    被--->dai->driver->ops->digital_mute(dai, mute);
                被--->int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute)
                            被--->static int soc_codec_close(struct snd_pcm_substream *substream)
                                            被--->asla应用层调用
                                            
                                            
                                            
                                            
问2:Asoc驱动中,音频数据流如何处理的?
答2:
在sound\soc\davinci\davinci-pcm.c
static int __init snd_davinci_pcm_init(void)
                    --->platform_driver_register(&davinci_pcm_driver)
                            --->davinci_soc_platform_probe(struct platform_device *pdev)
                                        --->snd_soc_register_platform(&pdev->dev, &davinci_soc_platform)
                                                    //被谁调用?    
                                                    --->davinci_pcm_new(struct snd_card *card,struct snd_soc_dai *dai, struct snd_pcm *pcm)
                                                            //播放
                                                            --->if (dai->driver->playback.channels_min) {
		                                                             ret = davinci_pcm_preallocate_dma_buffer(pcm,
		                                                    //录音
		                                                    --->if (dai->driver->capture.channels_min) {
		                                                            ret = davinci_pcm_preallocate_dma_buffer(pcm,
		                                                                                //分配dma内存 
		                                                                            --->dma_alloc_writecombine  



		                                                                            
问3:谁来调用davinci_pcm_new?
答3:
static struct snd_soc_platform_driver davinci_soc_platform = {
	.ops =		&davinci_pcm_ops,
	.pcm_new = 	davinci_pcm_new,
	.pcm_free = 	davinci_pcm_free,
};

在sound\soc\Soc-core.c
/* create a new pcm */
static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
                --->platform->driver->pcm_new(rtd->card->snd_card, codec_dai, pcm);
                                                                              
                                                     


评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值