Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
d807500a
Commit
d807500a
authored
Mar 24, 2009
by
Takashi Iwai
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'topic/pcm-cleanup' into for-linus
parents
c7ccfd06
8b22d943
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
102 additions
and
61 deletions
+102
-61
include/sound/pcm.h
include/sound/pcm.h
+0
-1
sound/core/pcm.c
sound/core/pcm.c
+0
-1
sound/core/pcm_lib.c
sound/core/pcm_lib.c
+102
-53
sound/core/pcm_timer.c
sound/core/pcm_timer.c
+0
-6
No files found.
include/sound/pcm.h
View file @
d807500a
...
@@ -364,7 +364,6 @@ struct snd_pcm_substream {
...
@@ -364,7 +364,6 @@ struct snd_pcm_substream {
/* -- timer section -- */
/* -- timer section -- */
struct
snd_timer
*
timer
;
/* timer */
struct
snd_timer
*
timer
;
/* timer */
unsigned
timer_running
:
1
;
/* time is running */
unsigned
timer_running
:
1
;
/* time is running */
spinlock_t
timer_lock
;
/* -- next substream -- */
/* -- next substream -- */
struct
snd_pcm_substream
*
next
;
struct
snd_pcm_substream
*
next
;
/* -- linked substreams -- */
/* -- linked substreams -- */
...
...
sound/core/pcm.c
View file @
d807500a
...
@@ -667,7 +667,6 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
...
@@ -667,7 +667,6 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
spin_lock_init
(
&
substream
->
self_group
.
lock
);
spin_lock_init
(
&
substream
->
self_group
.
lock
);
INIT_LIST_HEAD
(
&
substream
->
self_group
.
substreams
);
INIT_LIST_HEAD
(
&
substream
->
self_group
.
substreams
);
list_add_tail
(
&
substream
->
link_list
,
&
substream
->
self_group
.
substreams
);
list_add_tail
(
&
substream
->
link_list
,
&
substream
->
self_group
.
substreams
);
spin_lock_init
(
&
substream
->
timer_lock
);
atomic_set
(
&
substream
->
mmap_count
,
0
);
atomic_set
(
&
substream
->
mmap_count
,
0
);
prev
=
substream
;
prev
=
substream
;
}
}
...
...
sound/core/pcm_lib.c
View file @
d807500a
...
@@ -125,23 +125,32 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
...
@@ -125,23 +125,32 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
}
}
}
}
#ifdef CONFIG_SND_PCM_XRUN_DEBUG
#define xrun_debug(substream) ((substream)->pstr->xrun_debug)
#else
#define xrun_debug(substream) 0
#endif
#define dump_stack_on_xrun(substream) do { \
if (xrun_debug(substream) > 1) \
dump_stack(); \
} while (0)
static
void
xrun
(
struct
snd_pcm_substream
*
substream
)
static
void
xrun
(
struct
snd_pcm_substream
*
substream
)
{
{
snd_pcm_stop
(
substream
,
SNDRV_PCM_STATE_XRUN
);
snd_pcm_stop
(
substream
,
SNDRV_PCM_STATE_XRUN
);
#ifdef CONFIG_SND_PCM_XRUN_DEBUG
if
(
xrun_debug
(
substream
))
{
if
(
substream
->
pstr
->
xrun_debug
)
{
snd_printd
(
KERN_DEBUG
"XRUN: pcmC%dD%d%c
\n
"
,
snd_printd
(
KERN_DEBUG
"XRUN: pcmC%dD%d%c
\n
"
,
substream
->
pcm
->
card
->
number
,
substream
->
pcm
->
card
->
number
,
substream
->
pcm
->
device
,
substream
->
pcm
->
device
,
substream
->
stream
?
'c'
:
'p'
);
substream
->
stream
?
'c'
:
'p'
);
if
(
substream
->
pstr
->
xrun_debug
>
1
)
dump_stack_on_xrun
(
substream
);
dump_stack
();
}
}
#endif
}
}
static
inline
snd_pcm_uframes_t
snd_pcm_update_hw_ptr_pos
(
struct
snd_pcm_substream
*
substream
,
static
snd_pcm_uframes_t
struct
snd_pcm_runtime
*
runtime
)
snd_pcm_update_hw_ptr_pos
(
struct
snd_pcm_substream
*
substream
,
struct
snd_pcm_runtime
*
runtime
)
{
{
snd_pcm_uframes_t
pos
;
snd_pcm_uframes_t
pos
;
...
@@ -150,17 +159,21 @@ static inline snd_pcm_uframes_t snd_pcm_update_hw_ptr_pos(struct snd_pcm_substre
...
@@ -150,17 +159,21 @@ static inline snd_pcm_uframes_t snd_pcm_update_hw_ptr_pos(struct snd_pcm_substre
pos
=
substream
->
ops
->
pointer
(
substream
);
pos
=
substream
->
ops
->
pointer
(
substream
);
if
(
pos
==
SNDRV_PCM_POS_XRUN
)
if
(
pos
==
SNDRV_PCM_POS_XRUN
)
return
pos
;
/* XRUN */
return
pos
;
/* XRUN */
#ifdef CONFIG_SND_DEBUG
if
(
pos
>=
runtime
->
buffer_size
)
{
if
(
pos
>=
runtime
->
buffer_size
)
{
snd_printk
(
KERN_ERR
"BUG: stream = %i, pos = 0x%lx, buffer size = 0x%lx, period size = 0x%lx
\n
"
,
substream
->
stream
,
pos
,
runtime
->
buffer_size
,
runtime
->
period_size
);
if
(
printk_ratelimit
())
{
snd_printd
(
KERN_ERR
"BUG: stream = %i, pos = 0x%lx, "
"buffer size = 0x%lx, period size = 0x%lx
\n
"
,
substream
->
stream
,
pos
,
runtime
->
buffer_size
,
runtime
->
period_size
);
}
pos
=
0
;
}
}
#endif
pos
-=
pos
%
runtime
->
min_align
;
pos
-=
pos
%
runtime
->
min_align
;
return
pos
;
return
pos
;
}
}
static
in
line
in
t
snd_pcm_update_hw_ptr_post
(
struct
snd_pcm_substream
*
substream
,
static
int
snd_pcm_update_hw_ptr_post
(
struct
snd_pcm_substream
*
substream
,
struct
snd_pcm_runtime
*
runtime
)
struct
snd_pcm_runtime
*
runtime
)
{
{
snd_pcm_uframes_t
avail
;
snd_pcm_uframes_t
avail
;
...
@@ -182,11 +195,21 @@ static inline int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream
...
@@ -182,11 +195,21 @@ static inline int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream
return
0
;
return
0
;
}
}
static
inline
int
snd_pcm_update_hw_ptr_interrupt
(
struct
snd_pcm_substream
*
substream
)
#define hw_ptr_error(substream, fmt, args...) \
do { \
if (xrun_debug(substream)) { \
if (printk_ratelimit()) { \
snd_printd("PCM: " fmt, ##args); \
} \
dump_stack_on_xrun(substream); \
} \
} while (0)
static
int
snd_pcm_update_hw_ptr_interrupt
(
struct
snd_pcm_substream
*
substream
)
{
{
struct
snd_pcm_runtime
*
runtime
=
substream
->
runtime
;
struct
snd_pcm_runtime
*
runtime
=
substream
->
runtime
;
snd_pcm_uframes_t
pos
;
snd_pcm_uframes_t
pos
;
snd_pcm_uframes_t
new_hw_ptr
,
hw_ptr_interrupt
;
snd_pcm_uframes_t
new_hw_ptr
,
hw_ptr_interrupt
,
hw_base
;
snd_pcm_sframes_t
delta
;
snd_pcm_sframes_t
delta
;
pos
=
snd_pcm_update_hw_ptr_pos
(
substream
,
runtime
);
pos
=
snd_pcm_update_hw_ptr_pos
(
substream
,
runtime
);
...
@@ -194,36 +217,53 @@ static inline int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *subs
...
@@ -194,36 +217,53 @@ static inline int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *subs
xrun
(
substream
);
xrun
(
substream
);
return
-
EPIPE
;
return
-
EPIPE
;
}
}
if
(
runtime
->
period_size
==
runtime
->
buffer_size
)
hw_base
=
runtime
->
hw_ptr_base
;
goto
__next_buf
;
new_hw_ptr
=
hw_base
+
pos
;
new_hw_ptr
=
runtime
->
hw_ptr_base
+
pos
;
hw_ptr_interrupt
=
runtime
->
hw_ptr_interrupt
+
runtime
->
period_size
;
hw_ptr_interrupt
=
runtime
->
hw_ptr_interrupt
+
runtime
->
period_size
;
delta
=
new_hw_ptr
-
hw_ptr_interrupt
;
delta
=
hw_ptr_interrupt
-
new_hw_ptr
;
if
(
hw_ptr_interrupt
>=
runtime
->
boundary
)
{
if
(
delta
>
0
)
{
hw_ptr_interrupt
-=
runtime
->
boundary
;
if
((
snd_pcm_uframes_t
)
delta
<
runtime
->
buffer_size
/
2
)
{
if
(
hw_base
<
runtime
->
boundary
/
2
)
#ifdef CONFIG_SND_PCM_XRUN_DEBUG
/* hw_base was already lapped; recalc delta */
if
(
runtime
->
periods
>
1
&&
substream
->
pstr
->
xrun_debug
)
{
delta
=
new_hw_ptr
-
hw_ptr_interrupt
;
snd_printd
(
KERN_ERR
"Unexpected hw_pointer value [1] (stream = %i, delta: -%ld, max jitter = %ld): wrong interrupt acknowledge?
\n
"
,
substream
->
stream
,
(
long
)
delta
,
runtime
->
buffer_size
/
2
);
}
if
(
substream
->
pstr
->
xrun_debug
>
1
)
if
(
delta
<
0
)
{
dump_stack
();
delta
+=
runtime
->
buffer_size
;
}
if
(
delta
<
0
)
{
#endif
hw_ptr_error
(
substream
,
return
0
;
"Unexpected hw_pointer value "
"(stream=%i, pos=%ld, intr_ptr=%ld)
\n
"
,
substream
->
stream
,
(
long
)
pos
,
(
long
)
hw_ptr_interrupt
);
/* 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
;
}
else
{
hw_base
+=
runtime
->
buffer_size
;
if
(
hw_base
>=
runtime
->
boundary
)
hw_base
=
0
;
new_hw_ptr
=
hw_base
+
pos
;
}
}
__next_buf:
runtime
->
hw_ptr_base
+=
runtime
->
buffer_size
;
if
(
runtime
->
hw_ptr_base
==
runtime
->
boundary
)
runtime
->
hw_ptr_base
=
0
;
new_hw_ptr
=
runtime
->
hw_ptr_base
+
pos
;
}
}
if
(
delta
>
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
;
}
if
(
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
&&
if
(
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
&&
runtime
->
silence_size
>
0
)
runtime
->
silence_size
>
0
)
snd_pcm_playback_silence
(
substream
,
new_hw_ptr
);
snd_pcm_playback_silence
(
substream
,
new_hw_ptr
);
runtime
->
hw_ptr_base
=
hw_base
;
runtime
->
status
->
hw_ptr
=
new_hw_ptr
;
runtime
->
status
->
hw_ptr
=
new_hw_ptr
;
runtime
->
hw_ptr_interrupt
=
new_hw_ptr
-
new_hw_ptr
%
runtime
->
period_size
;
runtime
->
hw_ptr_interrupt
=
hw_ptr_interrupt
;
return
snd_pcm_update_hw_ptr_post
(
substream
,
runtime
);
return
snd_pcm_update_hw_ptr_post
(
substream
,
runtime
);
}
}
...
@@ -233,7 +273,7 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream)
...
@@ -233,7 +273,7 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream)
{
{
struct
snd_pcm_runtime
*
runtime
=
substream
->
runtime
;
struct
snd_pcm_runtime
*
runtime
=
substream
->
runtime
;
snd_pcm_uframes_t
pos
;
snd_pcm_uframes_t
pos
;
snd_pcm_uframes_t
old_hw_ptr
,
new_hw_ptr
;
snd_pcm_uframes_t
old_hw_ptr
,
new_hw_ptr
,
hw_base
;
snd_pcm_sframes_t
delta
;
snd_pcm_sframes_t
delta
;
old_hw_ptr
=
runtime
->
status
->
hw_ptr
;
old_hw_ptr
=
runtime
->
status
->
hw_ptr
;
...
@@ -242,29 +282,38 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream)
...
@@ -242,29 +282,38 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream)
xrun
(
substream
);
xrun
(
substream
);
return
-
EPIPE
;
return
-
EPIPE
;
}
}
new_hw_ptr
=
runtime
->
hw_ptr_base
+
pos
;
hw_base
=
runtime
->
hw_ptr_base
;
new_hw_ptr
=
hw_base
+
pos
;
delta
=
old_hw_ptr
-
new_hw_ptr
;
if
(
delta
>
0
)
{
delta
=
new_hw_ptr
-
old_hw_ptr
;
if
((
snd_pcm_uframes_t
)
delta
<
runtime
->
buffer_size
/
2
)
{
if
(
delta
<
0
)
{
#ifdef CONFIG_SND_PCM_XRUN_DEBUG
delta
+=
runtime
->
buffer_size
;
if
(
runtime
->
periods
>
2
&&
substream
->
pstr
->
xrun_debug
)
{
if
(
delta
<
0
)
{
snd_printd
(
KERN_ERR
"Unexpected hw_pointer value [2] (stream = %i, delta: -%ld, max jitter = %ld): wrong interrupt acknowledge?
\n
"
,
substream
->
stream
,
(
long
)
delta
,
runtime
->
buffer_size
/
2
);
hw_ptr_error
(
substream
,
if
(
substream
->
pstr
->
xrun_debug
>
1
)
"Unexpected hw_pointer value [2] "
dump_stack
();
"(stream=%i, pos=%ld, old_ptr=%ld)
\n
"
,
}
substream
->
stream
,
(
long
)
pos
,
#endif
(
long
)
old_hw_ptr
);
return
0
;
return
0
;
}
}
runtime
->
hw_ptr_base
+=
runtime
->
buffer_size
;
hw_base
+=
runtime
->
buffer_size
;
if
(
runtime
->
hw_ptr_base
==
runtime
->
boundary
)
if
(
hw_base
>=
runtime
->
boundary
)
runtime
->
hw_ptr_base
=
0
;
hw_base
=
0
;
new_hw_ptr
=
runtime
->
hw_ptr_base
+
pos
;
new_hw_ptr
=
hw_base
+
pos
;
}
if
(
delta
>
runtime
->
period_size
&&
runtime
->
periods
>
1
)
{
hw_ptr_error
(
substream
,
"hw_ptr skipping! "
"(pos=%ld, delta=%ld, period=%ld)
\n
"
,
(
long
)
pos
,
(
long
)
delta
,
(
long
)
runtime
->
period_size
);
return
0
;
}
}
if
(
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
&&
if
(
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
&&
runtime
->
silence_size
>
0
)
runtime
->
silence_size
>
0
)
snd_pcm_playback_silence
(
substream
,
new_hw_ptr
);
snd_pcm_playback_silence
(
substream
,
new_hw_ptr
);
runtime
->
hw_ptr_base
=
hw_base
;
runtime
->
status
->
hw_ptr
=
new_hw_ptr
;
runtime
->
status
->
hw_ptr
=
new_hw_ptr
;
return
snd_pcm_update_hw_ptr_post
(
substream
,
runtime
);
return
snd_pcm_update_hw_ptr_post
(
substream
,
runtime
);
...
...
sound/core/pcm_timer.c
View file @
d807500a
...
@@ -85,25 +85,19 @@ static unsigned long snd_pcm_timer_resolution(struct snd_timer * timer)
...
@@ -85,25 +85,19 @@ static unsigned long snd_pcm_timer_resolution(struct snd_timer * timer)
static
int
snd_pcm_timer_start
(
struct
snd_timer
*
timer
)
static
int
snd_pcm_timer_start
(
struct
snd_timer
*
timer
)
{
{
unsigned
long
flags
;
struct
snd_pcm_substream
*
substream
;
struct
snd_pcm_substream
*
substream
;
substream
=
snd_timer_chip
(
timer
);
substream
=
snd_timer_chip
(
timer
);
spin_lock_irqsave
(
&
substream
->
timer_lock
,
flags
);
substream
->
timer_running
=
1
;
substream
->
timer_running
=
1
;
spin_unlock_irqrestore
(
&
substream
->
timer_lock
,
flags
);
return
0
;
return
0
;
}
}
static
int
snd_pcm_timer_stop
(
struct
snd_timer
*
timer
)
static
int
snd_pcm_timer_stop
(
struct
snd_timer
*
timer
)
{
{
unsigned
long
flags
;
struct
snd_pcm_substream
*
substream
;
struct
snd_pcm_substream
*
substream
;
substream
=
snd_timer_chip
(
timer
);
substream
=
snd_timer_chip
(
timer
);
spin_lock_irqsave
(
&
substream
->
timer_lock
,
flags
);
substream
->
timer_running
=
0
;
substream
->
timer_running
=
0
;
spin_unlock_irqrestore
(
&
substream
->
timer_lock
,
flags
);
return
0
;
return
0
;
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment