*参照元 [#qcd14da2]
#backlinks

*説明 [#zfdda6dc]
-パス: [[linux-2.6.33/sound/core/pcm_lib.c]]

-FIXME: これは何?
--説明


**引数 [#e34af82b]
-struct snd_pcm_substream *substream
--
--[[linux-2.6.33/snd_pcm_substream]]


**返り値 [#y8db3630]
-int
--


**参考 [#ze5301c2]


*実装 [#m6597aef]
 static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	snd_pcm_uframes_t pos;
 	snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_ptr_interrupt, hw_base;
 	snd_pcm_sframes_t hdelta, delta;
 	unsigned long jdelta;
 
-
--[[linux-2.6.33/snd_pcm_runtime]]
-
--[[linux-2.6.33/snd_pcm_uframes_t]]
-
--[[linux-2.6.33/snd_pcm_sframes_t]]

 	old_hw_ptr = runtime->status->hw_ptr;
 	pos = snd_pcm_update_hw_ptr_pos(substream, runtime);
 	if (pos == SNDRV_PCM_POS_XRUN) {
 		xrun(substream);
 		return -EPIPE;
 	}
-
--[[linux-2.6.33/snd_pcm_update_hw_ptr_pos()]]
-
--[[linux-2.6.33/SNDRV_PCM_POS_XRUN]]
-
--[[linux-2.6.33/xrun()]]

 	if (xrun_debug(substream, 8)) {
-
--[[linux-2.6.33/xrun_debug()]]

 		char name[16];
 		pcm_debug_name(substream, name, sizeof(name));
 		snd_printd("period_update: %s: pos=0x%x/0x%x/0x%x, "
 			   "hwptr=0x%lx, hw_base=0x%lx, hw_intr=0x%lx\n",
 			   name, (unsigned int)pos,
 			   (unsigned int)runtime->period_size,
 			   (unsigned int)runtime->buffer_size,
 			   (unsigned long)old_hw_ptr,
 			   (unsigned long)runtime->hw_ptr_base,
 			   (unsigned long)runtime->hw_ptr_interrupt);
-
--[[linux-2.6.33/pcm_debug_name()]]
-
--[[linux-2.6.33/snd_printd()]]

 	}
 	hw_base = runtime->hw_ptr_base;
 	new_hw_ptr = hw_base + pos;
 	hw_ptr_interrupt = runtime->hw_ptr_interrupt + runtime->period_size;
 	delta = new_hw_ptr - hw_ptr_interrupt;
 	if (hw_ptr_interrupt >= runtime->boundary) {
 		hw_ptr_interrupt -= runtime->boundary;
 		if (hw_base < runtime->boundary / 2)
 			/* hw_base was already lapped; recalc delta */
 			delta = new_hw_ptr - hw_ptr_interrupt;
 	}
 	if (delta < 0) {
 		if (runtime->periods == 1 || new_hw_ptr < old_hw_ptr)
 			delta += runtime->buffer_size;
 		if (delta < 0) {
 			hw_ptr_error(substream, 
 				     "Unexpected hw_pointer value "
 				     "(stream=%i, pos=%ld, intr_ptr=%ld)\n",
 				     substream->stream, (long)pos,
 				     (long)hw_ptr_interrupt);
-
--[[linux-2.6.33/hw_ptr_error()]]

 #if 1
 			/* simply skipping the hwptr update seems more
 			 * robust in some cases, e.g. on VMware with
 			 * inaccurate timer source
 			 */
 			return 0; /* skip this update */
 #else
 			/* rebase to interrupt position */
 			hw_base = new_hw_ptr = hw_ptr_interrupt;
 			/* align hw_base to buffer_size */
 			hw_base -= hw_base % runtime->buffer_size;
 			delta = 0;
 #endif
 		} else {
 			hw_base += runtime->buffer_size;
 			if (hw_base >= runtime->boundary)
 				hw_base = 0;
 			new_hw_ptr = hw_base + pos;
 		}
 	}
 
 	/* Do jiffies check only in xrun_debug mode */
 	if (!xrun_debug(substream, 4))
 		goto no_jiffies_check;
 
 	/* Skip the jiffies check for hardwares with BATCH flag.
 	 * Such hardware usually just increases the position at each IRQ,
 	 * thus it can't give any strange position.
 	 */
 	if (runtime->hw.info & SNDRV_PCM_INFO_BATCH)
 		goto no_jiffies_check;
-
--[[linux-2.6.33/SNDRV_PCM_INFO_BATCH]]

 	hdelta = new_hw_ptr - old_hw_ptr;
 	if (hdelta < runtime->delay)
 		goto no_jiffies_check;
 	hdelta -= runtime->delay;
 	jdelta = jiffies - runtime->hw_ptr_jiffies;
 	if (((hdelta * HZ) / runtime->rate) > jdelta + HZ/100) {
-
--[[linux-2.6.33/HZ]]

 		delta = jdelta /
 			(((runtime->period_size * HZ) / runtime->rate)
 								+ HZ/100);
 		hw_ptr_error(substream,
 			     "hw_ptr skipping! [Q] "
 			     "(pos=%ld, delta=%ld, period=%ld, "
 			     "jdelta=%lu/%lu/%lu)\n",
 			     (long)pos, (long)hdelta,
 			     (long)runtime->period_size, jdelta,
 			     ((hdelta * HZ) / runtime->rate), delta);
 		hw_ptr_interrupt = runtime->hw_ptr_interrupt +
 				   runtime->period_size * delta;
 		if (hw_ptr_interrupt >= runtime->boundary)
 			hw_ptr_interrupt -= runtime->boundary;
 		/* rebase to interrupt position */
 		hw_base = new_hw_ptr = hw_ptr_interrupt;
 		/* align hw_base to buffer_size */
 		hw_base -= hw_base % runtime->buffer_size;
 		delta = 0;
 	}
  no_jiffies_check:
 	if (delta > runtime->period_size + runtime->period_size / 2) {
 		hw_ptr_error(substream,
 			     "Lost interrupts? "
 			     "(stream=%i, delta=%ld, intr_ptr=%ld)\n",
 			     substream->stream, (long)delta,
 			     (long)hw_ptr_interrupt);
 		/* rebase hw_ptr_interrupt */
 		hw_ptr_interrupt =
 			new_hw_ptr - new_hw_ptr % runtime->period_size;
 	}
 	runtime->hw_ptr_interrupt = hw_ptr_interrupt;
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
 	    runtime->silence_size > 0)
 		snd_pcm_playback_silence(substream, new_hw_ptr);
 
-
--[[linux-2.6.33/snd_pcm_playback_silence()]]

 	if (runtime->status->hw_ptr == new_hw_ptr)
 		return 0;
 
 	runtime->hw_ptr_base = hw_base;
 	runtime->status->hw_ptr = new_hw_ptr;
 	runtime->hw_ptr_jiffies = jiffies;
 	if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
 		snd_pcm_gettime(runtime, (struct timespec *)&runtime->status->tstamp);
 
-
--[[linux-2.6.33/SNDRV_PCM_TSTAMP_ENABLE]]
-
--[[linux-2.6.33/snd_pcm_gettime()]]
-
--[[linux-2.6.33/timespec]]

 	return snd_pcm_update_hw_ptr_post(substream, runtime);
-
--[[linux-2.6.33/snd_pcm_update_hw_ptr_post()]]

 }


*コメント [#w8ebf5b2]


トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS