浅析ac97声卡intel8x0的runtime->dma_area是怎么获取的
runtime->dma_area的DMA内存空间指向substream->dma_buffer申请到的DMA内存[luther.gliethttp]
ioctl(SNDRV_PCM_IOCTL_HW_PARAMS)
==> snd_pcm_f_ops.unlocked_ioctl即:snd_pcm_playback_ioctl
==> snd_pcm_playback_ioctl
==> snd_pcm_playback_ioctl1
==> snd_pcm_common_ioctl1
case SNDRV_PCM_IOCTL_HW_PARAMS:
return snd_pcm_hw_params_user(substream, arg);
==> snd_pcm_hw_params_user
==> snd_pcm_hw_params
==> substream->ops->hw_params即snd_intel8x0_playback_ops.hw_params
==> snd_intel8x0_hw_params
==> snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
申请可供DMA使用的DDR内存缓冲区[luther.gliethttp]
int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size)
{
struct snd_pcm_runtime *runtime;
struct snd_dma_buffer *dmab = NULL;
if (PCM_RUNTIME_CHECK(substream))
return -EINVAL;
if (snd_BUG_ON(substream->dma_buffer.dev.type ==
SNDRV_DMA_TYPE_UNKNOWN))
return -EINVAL;
runtime = substream->runtime;
if (runtime->dma_buffer_p) {
/* perphaps, we might free the large DMA memory region
to save some space here, but the actual solution
costs us less time */
if (runtime->dma_buffer_p->bytes >= size) {
runtime->dma_bytes = size;
return 0; /* ok, do not change */
}
snd_pcm_lib_free_pages(substream);
}
if (substream->dma_buffer.area != NULL &&
substream->dma_buffer.bytes >= size) {
// 将在声卡probe时统一创建的substream->dma_buffer作为dmab,赋值给
// runtime使用[luther.gliethttp]
《浅析ac97声卡intel8x0的DMA内存substream->dma_buffer什么时候被赋值》 dmab = &substream->dma_buffer; /* use the pre-allocated buffer */
} else {
dmab = kzalloc(sizeof(*dmab), GFP_KERNEL);
if (! dmab)
return -ENOMEM;
dmab->dev = substream->dma_buffer.dev;
if (snd_dma_alloc_pages(substream->dma_buffer.dev.type,
substream->dma_buffer.dev.dev,
size, dmab) < 0) {
kfree(dmab);
return -ENOMEM;
}
}
snd_pcm_set_runtime_buffer(substream, dmab);
runtime->dma_bytes = size;
return 1; /* area was changed */
}
==> snd_pcm_set_runtime_buffer(substream, dmab);
static inline void snd_pcm_set_runtime_buffer(struct snd_pcm_substream *substream,
struct snd_dma_buffer *bufp)
{
struct snd_pcm_runtime *runtime = substream->runtime;
if (bufp) {
runtime->dma_buffer_p = bufp;
runtime->dma_area = bufp->area; // 设置runtime的dma空间[luther.gliethttp]
runtime->dma_addr = bufp->addr;
runtime->dma_bytes = bufp->bytes;
} else {
runtime->dma_buffer_p = NULL;
runtime->dma_area = NULL;
runtime->dma_addr = 0;
runtime->dma_bytes = 0;
}
}
[21154.679954] ==============================
[21154.686146] Intel ICH 0000:00:1f.5: PCI INT B -> GSI 17 (level, low) -> IRQ 17
[21154.686393] +++++snd_dma_alloc_pages++size=1536,vaddr=f2acd000,paddr=32acd000, type=2+++++
[21154.686408] Intel ICH 0000:00:1f.5: setting latency timer to 64
[21154.953628] ****************Intel ICH5
[21154.953668] +++++snd_dma_alloc_pages++size=65536,vaddr=c2040000,paddr=02040000, type=2+++++
[21154.953706] +++++snd_dma_alloc_pages++size=65536,vaddr=c2090000,paddr=02090000, type=2+++++
[21154.953735] ****************Intel ICH5 - MIC ADC
[21154.953760] ****************Intel ICH5 - MIC2 ADC
[21154.953785] ****************Intel ICH5 - ADC2
[21154.953810] ****************Intel ICH5 - IEC958
[21154.953850] +++++snd_dma_alloc_pages++size=65536,vaddr=c2000000,paddr=02000000, type=2+++++
[21155.008531] intel8x0_measure_ac97_clock: measured 54608 usecs (2632 samples)
[21155.008540] intel8x0: clocking to 48000
[21185.665434] snd_pcm_lib_malloc_pages+++++++++++substream->dma_buffer.bytes=65536, size=65536+++++++++++++
[21185.665699] ######snd_intel8x0_pcm_prepare###physbuf=02040000, size=65536, fragsize=8192, chip->device_type=1