AnsweredAssumed Answered

关于IMX6ULL alsa 问题

Question asked by chen dong on Mar 25, 2020
Latest reply on Mar 25, 2020 by Wigros Sun

你好:

我现在正在做基于imx6u'll的 alsa 开发,我发现一个问题,在6ull下,snd_pcm_open()后,按照理论来说PCM 的状态是SNDRV_PCM_STATE_OPEN,但是我发现无论怎设置只要打开了,任何时候都是SNDRV_PCM_STATE_RUNNING 状态,这样就是陷入死循环。但是这个我在IMX8MM 系统下运行是正常的。不知道这个和SAI 驱动有没有关系。谢谢。

######################################

按理说是这样的步骤的,下面这些在imx8mm 系统下是对应的,不知道为何在imx6下始终只有SNDRV_PCM_STATE_RUNNING的状态,

在ALSA最底层写函数snd_pcm_lib_write1中,首先检测当前PCM的状态,是 SNDRV_PCM_STATE_PREPARED、SNDRV_PCM_STATE_RUNNING、 SNDRV_PCM_STATE_PAUSED这三种状态下,驱动就开始transfer数据,如果为SNDRV_PCM_STATE_XRUN返回-EPIPE错误,如果为SNDRV_PCM_STATE_SUSPENDED,就返回 -ESTRPIPE;其他状态均返回-EBADFD错误。

    在打开一个PCM流时,PCM的状态为SNDRV_PCM_STATE_OPEN ,给这个流配置参数,如channel数、采样率、采样精度后,PCM的状态配置为SNDRV_PCM_STATE_SETUP,在写数据之前,需要提示驱动去各继各位,准备工作,这时候去prepare一下,就像是考试前的动员大会一样,让你热血沸腾、充满信心,prepare后PCM流的状态为SNDRV_PCM_STATE_PREPARED,开始写数据的过程中,PCM的状态会设置为 SNDRV_PCM_STATE_RUNNING,播放完数据后,通常需要去drain一下来sync,在调snd_pcm_drain过程中,PCM的状态为PCM的状态,drain完以后PCM的状态为会设置为SNDRV_PCM_STATE_SETUP,因此在再次写数据的时候,驱动就会返回-EBADFD的错误,那么如何有效避免呢?

     办法当然是有的,alsa-lib中提供了非常完善的接口。笔者也曾碰到过-EBADFD的错误,很烦人啊!出了错后,alsa驱动就需要恢复错误状态,或者干脆重新打开一次播放流程,但是这样做的后果就是有可能带来“兹兹”噪音或者如“都-都”这样的怪音,这种现象出来对产品来说肯定是不利的,因此在上层再次调用alsa写函数的时候,首先去获取一些当前PCM的状态是什么,用snd_pcm_state函数,如果当前PCM为 SNDRV_PCM_STATE_SETUP,只需要snd_pcm_prepare一下,就可以进行正常的数据写操作。

    在系统进入省电模式时,驱动会执行suspend,PCM状态变为SNDRV_PCM_STATE_SUSPENDED,在唤醒系统后,笔者在adroid系统中发现,PCM的状态仍然为SNDRV_PCM_STATE_SUSPENDED状态,在这种状态下,直接进行写操作,无疑会带来-EBADFD的错误。如果在写数据的之前,检测到的pcm状态为SNDRV_PCM_STATE_SUSPENDED,就可以先snd_pcm_resume,再snd_pcm_prepare一下,alsa就可以回到正常工作状态,可以正常的写数据。
————————————————

Outcomes