linux-2.6.33/snd_pcm_update_hw_ptr_interrupt()
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
検索
|
最終更新
|
ヘルプ
|
ログイン
]
開始行:
*参照元 [#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_pc...
{
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_uframes_t pos;
snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_ptr_interr...
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-...
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...
* 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...
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->...
-
--[[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]
終了行:
*参照元 [#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_pc...
{
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_uframes_t pos;
snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_ptr_interr...
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-...
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...
* 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...
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->...
-
--[[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]
ページ名: