tlvaic3101音频芯片开发笔记调试技巧
2016-08-19 18:05
477 查看
</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);
相关文章推荐
- IOS开发笔记 - 调试技巧之自定义宏输出
- Visual C++开发工具与调试技巧整理
- Visual C++开发工具与调试技巧整理
- Visual C++开发工具与调试技巧整理
- Visual C++开发工具与调试技巧整理
- Visual C++开发工具与调试技巧整理
- Visual C++开发工具与调试技巧整理
- Visual C++开发工具与调试技巧整理
- Visual C++开发工具与调试技巧整理
- Visual C++开发工具与调试技巧整理 - Azure Product - 游戏创造网--社区 - powered by X-Space
- Visual C++开发工具与调试技巧整理
- (转)Visual C++开发工具与调试技巧整理
- Visual C++开发工具与调试技巧整理
- Visual C 开发工具与调试技巧整理
- Visual C++开发工具与调试技巧整理
- Visual C++开发工具与调试技巧整理
- (转)Visual C++开发工具与调试技巧整理
- Visual C++开发工具与调试技巧整理
- Visual C++开发工具与调试技巧整理
- win32开发环境下调试opencv程序的一些技巧