alsa声卡dev_snd_pcmC0D0p的open打开流程 下载本文

cnt = igetdword(chip, ICHREG(ALI_SCR)); cnt &= ~ICH_ALI_SC_PCM_246_MASK; if (runtime->channels == 4 || dbl) cnt |= ICH_ALI_SC_PCM_4; else if (runtime->channels == 6) cnt |= ICH_ALI_SC_PCM_6;

iputdword(chip, ICHREG(ALI_SCR), cnt); break;

case DEVICE_SIS:

cnt = igetdword(chip, ICHREG(GLOB_CNT)); cnt &= ~ICH_SIS_PCM_246_MASK; if (runtime->channels == 4 || dbl) cnt |= ICH_SIS_PCM_4;

else if (runtime->channels == 6) cnt |= ICH_SIS_PCM_6;

iputdword(chip, ICHREG(GLOB_CNT), cnt); break; default:

cnt = igetdword(chip, ICHREG(GLOB_CNT));

cnt &= ~(ICH_PCM_246_MASK | ICH_PCM_20BIT); if (runtime->channels == 4 || dbl) cnt |= ICH_PCM_4;

else if (runtime->channels == 6) cnt |= ICH_PCM_6;

else if (runtime->channels == 8) cnt |= ICH_PCM_8;

if (chip->device_type == DEVICE_NFORCE) {

/* reset to 2ch once to keep the 6 channel data in alignment, * to start from Front Left always */

if (cnt & ICH_PCM_246_MASK) {

iputdword(chip, ICHREG(GLOB_CNT), cnt & ~ICH_PCM_246_MASK); spin_unlock_irq(&chip->reg_lock);

msleep(50); /* grrr... */

spin_lock_irq(&chip->reg_lock); }

} else if (chip->device_type == DEVICE_INTEL_ICH4) { if (runtime->sample_bits > 16) cnt |= ICH_PCM_20BIT; }

iputdword(chip, ICHREG(GLOB_CNT), cnt); break; }

spin_unlock_irq(&chip->reg_lock);

}

ioctl(SNDRV_PCM_IOCTL_START) ==> snd_pcm_playback_ioctl ==> snd_pcm_playback_ioctl1 ==> snd_pcm_common_ioctl1

==> snd_pcm_action_lock_irq(&snd_pcm_action_start, substream, SNDRV_PCM_STATE_RUNNING); ==> snd_pcm_action_single // state等于SNDRV_PCM_STATE_RUNNING static struct action_ops snd_pcm_action_start = { .pre_action = snd_pcm_pre_start, .do_action = snd_pcm_do_start,

.undo_action = snd_pcm_undo_start,

.post_action = snd_pcm_post_start };

ops->pre_action(substream, state); ops->do_action(substream, state); ops->post_action(substream, state);

上面ops就是之前提到的snd_pcm_action_start

==> snd_pcm_do_start

==> substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_START);即snd_intel8x0_playback_ops.trigger

==> snd_intel8x0_pcm_trigger启动ac97数据传输

以上都只是执行一次[luther.gliethttp]

只要发送音频数据,就会执行该ioctl更新pointer

ioctl(SNDRV_PCM_IOCTL_HWSYNC) ==> snd_pcm_playback_ioctl ==> snd_pcm_playback_ioctl1 ==> snd_pcm_common_ioctl1 ==> snd_pcm_hwsync

case SNDRV_PCM_STATE_RUNNING:

if ((err = snd_pcm_update_hw_ptr(substream)) < 0)

break;

==> snd_pcm_update_hw_ptr

==> snd_pcm_update_hw_ptr_post ==> snd_pcm_update_hw_ptr_pos

==> substream->ops->pointer(substream);即snd_intel8x0_playback_ops.pointer

==> snd_intel8x0_pcm_pointer // 更新dma缓冲区数据最后可用数据索引值[luther.gliethttp]