pcm_open()栈
用户的pcm_open()相当于先对ASoC各个驱动模块startup(),再做hw_params()。
pcm_open()
pcm->fd = open("/dev/snd/pcmC0D0c")
snd_pcm_capture_open()
snd_pcm_open(SNDRV_PCM_STREAM_CAPTURE)
snd_pcm_open_file()
snd_pcm_open_substream()
substream->ops->open()
soc_pcm_open()
cpu_dai->driver->ops->startup()
platform->driver->ops->open()
codec_dai->driver->ops->startup()
rtd->dai_link->ops->startup()
ioctl(pcm->fd, SNDRV_PCM_IOCTL_HW_PARAMS, ¶ms)
snd_pcm_hw_params_user()
snd_pcm_hw_params()
substream->ops->hw_params()
soc_pcm_hw_params()
rtd->dai_link->ops->hw_params()
dai->driver->ops->hw_params()
platform->driver->ops->hw_params()
ioctl(pcm->fd, SNDRV_PCM_IOCTL_SW_PARAMS, &sparams)
pcm_read()栈
用户的pcm_read()相当于做从内核缓冲区到用户缓冲区的copy_to_user()。即把硬件写到内核缓冲区的数据拷贝到用户缓冲区。(mmap模式例外,其没有数据拷贝的动作,性能更好。)
pcm_read()
if (!pcm->running)
pcm_start()
pcm->running = 1
ioctl(pcm->fd, SNDRV_PCM_IOCTL_READI_FRAMES, &x)
snd_pcm_lib_read()
snd_pcm_lib_read1(transfer)
transfer(substream, appl_ofs, data, offset, frames)
snd_pcm_lib_read_transfer()
substream->ops->copy() *or* copy_to_user()
pcm_start()栈
用户的pcm_start()相当于对ASoC的各个驱动模块做prepare()和trigger(START)动作。
pcm_start()
ioctl(pcm->fd, SNDRV_PCM_IOCTL_PREPARE)
snd_pcm_prepare()
snd_pcm_do_prepare()
substream->ops->prepare()
soc_pcm_prepare()
rtd->dai_link->ops->prepare()
platform->driver->ops->prepare()
codec_dai->driver->ops->prepare()
cpu_dai->driver->ops->prepare()
ioctl(pcm->fd, SNDRV_PCM_IOCTL_START)
snd_pcm_action_lock_irq()
snd_pcm_do_start()
substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_START)
soc_pcm_trigger()
codec_dai->driver->ops->trigger()
platform->driver->ops->trigger()
cpu_dai->driver->ops->trigger()
rtd->dai_link->ops->trigger()
pcm_close()栈
用户的pcm_close()相当于对ASoC的各个驱动模块做trigger(STOP), hw_free()和shutdown()动作。
pcm_close()
close(pcm->fd)
snd_pcm_release()
snd_pcm_release_substream()
snd_pcm_drop(substream)
snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP)
snd_pcm_do_stop()
substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP)
soc_pcm_trigger()
codec_dai->driver->ops->trigger()
platform->driver->ops->trigger()
cpu_dai->driver->ops->trigger()
rtd->dai_link->ops->trigger()
if (substream->hw_opened)
if (substream->ops->hw_free != NULL)
substream->ops->hw_free(substream)
substream->ops->close(substream)
soc_pcm_close()
cpu_dai->driver->ops->shutdown()
codec_dai->driver->ops->shutdown()
rtd->dai_link->ops->shutdown()
platform->driver->ops->close()
substream->hw_opened = 0