ALSA驱动、设备函数调用关系

414 阅读1分钟

\

soc_probe
==> snd_soc_register_card或者snd_soc_register_dai或者snd_soc_register_platform或者snd_soc_register_codec
==> snd_soc_instantiate_cards
==> snd_soc_instantiate_card
==> codec_dev->probe
==> uda134x_soc_probe
==> snd_soc_new_pcms
==> soc_new_pcm
==> snd_pcm_new

snd_soc_new_pcms
snd_card_create
snd_ctl_create
snd_ctl_dev_register创建"controlC%i"声卡对应的控制节点,
他的fops为snd_ctl_f_ops

snd_pcm_dev_register
snd_register_device_for_dev
创建"pcmC%iD%ip"或者"pcmC%iD%ic"设备节点,它的fops为snd_pcm_f_ops[2]

snd_pcm_f_ops[2]
==> snd_pcm_playback_open或者snd_pcm_capture_open
==> snd_pcm_open或者oss的snd_pcm_oss_f_reg.snd_pcm_oss_open,这就对应/dev/dsp了
==> snd_pcm_open_file或者oss的snd_pcm_oss_open_file
==> snd_pcm_open_substream
==> soc_pcm_open

/* 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,
};
==> soc_pcm_open
cpu_dai->ops->startup       // 无
platform->pcm_ops->open     // s3c_dma_open 分配DMA空间
codec_dai->ops->startup     // uda134x_startup 
card_dai_link->ops->startup // s3c24xx_uda134x_startup 获取clock时钟源

// cpu_dai单元
struct snd_soc_dai s3c24xx_i2s_dai = {


.name = "s3c24xx-i2s",
.id = 0,
.probe = s3c24xx_i2s_probe,
.suspend = s3c24xx_i2s_suspend,
.resume = s3c24xx_i2s_resume,
.playback = {


.channels_min = 2,
.channels_max = 2,
.rates = S3C24XX_I2S_RATES,
.formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,},
.capture = {


.channels_min = 2,
.channels_max = 2,
.rates = S3C24XX_I2S_RATES,
.formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,},
.ops = &s3c24xx_i2s_dai_ops,
};
//platform单元
struct snd_soc_platform s3c24xx_soc_platform = {


.name        = "s3c24xx-audio",
.pcm_ops     = &s3c_dma_ops,
.pcm_new    = s3c_dma_new,
.pcm_free    = s3c_dma_free_dma_buffers,
};

static struct snd_pcm_ops s3c_dma_ops = {


.open        = s3c_dma_open,
.close        = s3c_dma_close,
.ioctl        = snd_pcm_lib_ioctl,
.hw_params    = s3c_dma_hw_params,
.hw_free    = s3c_dma_hw_free,
.prepare    = s3c_dma_prepare,
.trigger    = s3c_dma_trigger,
.pointer    = s3c_dma_pointer,
.mmap        = s3c_dma_mmap,
};
// codec_dai单元
struct snd_soc_dai uda134x_dai = {


.name = "UDA134X",
/* playback capabilities */
.playback = {


.stream_name = "Playback",
.channels_min = 1,
.channels_max = 2,
.rates = UDA134X_RATES,
.formats = UDA134X_FORMATS,
},
/* capture capabilities */
.capture = {


.stream_name = "Capture",
.channels_min = 1,
.channels_max = 2,
.rates = UDA134X_RATES,
.formats = UDA134X_FORMATS,
},
/* pcm operations */
.ops = &uda134x_dai_ops,
};

//card_dai_link单元
static struct snd_soc_dai_link s3c24xx_uda134x_dai_link = {


.name = "UDA134X",
.stream_name = "UDA134X",
.codec_dai = &uda134x_dai,
.cpu_dai = &s3c24xx_i2s_dai,
.ops = &s3c24xx_uda134x_ops,\

};

\

\

Pcm.c

snd_pcm_control_ioctl()

case SNDRV_CTL_IOCTL_PCM_INFO:

*  S1:get params infofrom userspace arg*

*  S2:get info->device

*  S3:get info->stream

*  S4:get info->subdevice

*  S5:get pcm from matching special card and device

 

*  S1:get pstrfrom &pcm->streams[stream]

*  S2:get substreamfrom pstr->substream

*  S3:Now! we got struct snd_pcm_substream*substream

*        which contents the struct snd_pcm_runtime*runtime;

 

snd_pcm_runtime里面有

       /* -- hardware description -- */

       struct snd_pcm_hardware hw;

       struct snd_pcm_hw_constraintshw_constraints;

 

 

xx_pcm.c

xx_pcm_hardware

xx_pcm_open()

xx_pcm_ops

xx_soc_platform

snd_soc_register_platform()

xx_soc_platform_init()

module_init