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]