Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
f3305da3
cloud-kernel
项目概览
openanolis
/
cloud-kernel
大约 1 年 前同步成功
通知
152
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
f3305da3
编写于
10月 20, 2010
作者:
T
Takashi Iwai
浏览文件
操作
浏览文件
下载
差异文件
Merge remote branch 'alsa/devel' into topic/misc
上级
83fc3bc0
5de9e45f
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
123 addition
and
16 deletion
+123
-16
sound/drivers/aloop.c
sound/drivers/aloop.c
+123
-16
未找到文件。
sound/drivers/aloop.c
浏览文件 @
f3305da3
...
...
@@ -39,6 +39,7 @@
#include <sound/core.h>
#include <sound/control.h>
#include <sound/pcm.h>
#include <sound/info.h>
#include <sound/initval.h>
MODULE_AUTHOR
(
"Jaroslav Kysela <perex@perex.cz>"
);
...
...
@@ -76,6 +77,7 @@ struct loopback_cable {
/* flags */
unsigned
int
valid
;
unsigned
int
running
;
unsigned
int
pause
;
};
struct
loopback_setup
{
...
...
@@ -184,6 +186,7 @@ static void loopback_timer_start(struct loopback_pcm *dpcm)
static
inline
void
loopback_timer_stop
(
struct
loopback_pcm
*
dpcm
)
{
del_timer
(
&
dpcm
->
timer
);
dpcm
->
timer
.
expires
=
0
;
}
#define CABLE_VALID_PLAYBACK (1 << SNDRV_PCM_STREAM_PLAYBACK)
...
...
@@ -252,7 +255,7 @@ static int loopback_trigger(struct snd_pcm_substream *substream, int cmd)
struct
snd_pcm_runtime
*
runtime
=
substream
->
runtime
;
struct
loopback_pcm
*
dpcm
=
runtime
->
private_data
;
struct
loopback_cable
*
cable
=
dpcm
->
cable
;
int
err
;
int
err
,
stream
=
1
<<
substream
->
stream
;
switch
(
cmd
)
{
case
SNDRV_PCM_TRIGGER_START
:
...
...
@@ -261,17 +264,36 @@ static int loopback_trigger(struct snd_pcm_substream *substream, int cmd)
return
err
;
dpcm
->
last_jiffies
=
jiffies
;
dpcm
->
pcm_rate_shift
=
0
;
spin_lock
(
&
cable
->
lock
);
cable
->
running
|=
stream
;
cable
->
pause
&=
~
stream
;
spin_unlock
(
&
cable
->
lock
);
loopback_timer_start
(
dpcm
);
cable
->
running
|=
(
1
<<
substream
->
stream
);
if
(
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
loopback_active_notify
(
dpcm
);
break
;
case
SNDRV_PCM_TRIGGER_STOP
:
cable
->
running
&=
~
(
1
<<
substream
->
stream
);
spin_lock
(
&
cable
->
lock
);
cable
->
running
&=
~
stream
;
cable
->
pause
&=
~
stream
;
spin_unlock
(
&
cable
->
lock
);
loopback_timer_stop
(
dpcm
);
if
(
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
loopback_active_notify
(
dpcm
);
break
;
case
SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
spin_lock
(
&
cable
->
lock
);
cable
->
pause
|=
stream
;
spin_unlock
(
&
cable
->
lock
);
loopback_timer_stop
(
dpcm
);
break
;
case
SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
spin_lock
(
&
cable
->
lock
);
dpcm
->
last_jiffies
=
jiffies
;
cable
->
pause
&=
~
stream
;
spin_unlock
(
&
cable
->
lock
);
loopback_timer_start
(
dpcm
);
break
;
default:
return
-
EINVAL
;
}
...
...
@@ -452,28 +474,30 @@ static void loopback_bytepos_update(struct loopback_pcm *dpcm,
}
}
static
void
loopback_pos_update
(
struct
loopback_cable
*
cable
)
static
unsigned
int
loopback_pos_update
(
struct
loopback_cable
*
cable
)
{
struct
loopback_pcm
*
dpcm_play
=
cable
->
streams
[
SNDRV_PCM_STREAM_PLAYBACK
];
struct
loopback_pcm
*
dpcm_capt
=
cable
->
streams
[
SNDRV_PCM_STREAM_CAPTURE
];
unsigned
long
delta_play
=
0
,
delta_capt
=
0
;
unsigned
int
running
;
spin_lock
(
&
cable
->
lock
);
if
(
cable
->
running
&
(
1
<<
SNDRV_PCM_STREAM_PLAYBACK
))
{
running
=
cable
->
running
^
cable
->
pause
;
if
(
running
&
(
1
<<
SNDRV_PCM_STREAM_PLAYBACK
))
{
delta_play
=
jiffies
-
dpcm_play
->
last_jiffies
;
dpcm_play
->
last_jiffies
+=
delta_play
;
}
if
(
cable
->
running
&
(
1
<<
SNDRV_PCM_STREAM_CAPTURE
))
{
if
(
running
&
(
1
<<
SNDRV_PCM_STREAM_CAPTURE
))
{
delta_capt
=
jiffies
-
dpcm_capt
->
last_jiffies
;
dpcm_capt
->
last_jiffies
+=
delta_capt
;
}
if
(
delta_play
==
0
&&
delta_capt
==
0
)
{
spin_unlock
(
&
cable
->
lock
);
return
;
return
running
;
}
if
(
delta_play
>
delta_capt
)
{
...
...
@@ -488,27 +512,27 @@ static void loopback_pos_update(struct loopback_cable *cable)
if
(
delta_play
==
0
&&
delta_capt
==
0
)
{
spin_unlock
(
&
cable
->
lock
);
return
;
return
running
;
}
/* note delta_capt == delta_play at this moment */
loopback_bytepos_update
(
dpcm_capt
,
delta_capt
,
BYTEPOS_UPDATE_COPY
);
loopback_bytepos_update
(
dpcm_play
,
delta_play
,
BYTEPOS_UPDATE_POSONLY
);
spin_unlock
(
&
cable
->
lock
);
return
running
;
}
static
void
loopback_timer_function
(
unsigned
long
data
)
{
struct
loopback_pcm
*
dpcm
=
(
struct
loopback_pcm
*
)
data
;
int
stream
;
unsigned
int
running
;
loopback_pos_update
(
dpcm
->
cable
);
stream
=
dpcm
->
substream
->
stream
;
if
(
dpcm
->
cable
->
running
&
(
1
<<
stream
))
running
=
loopback_pos_update
(
dpcm
->
cable
);
if
(
running
&
(
1
<<
dpcm
->
substream
->
stream
))
{
loopback_timer_start
(
dpcm
);
if
(
dpcm
->
period_update_pending
)
{
dpcm
->
period_update_pending
=
0
;
if
(
dpcm
->
cable
->
running
&
(
1
<<
stream
))
if
(
dpcm
->
period_update_pending
)
{
dpcm
->
period_update_pending
=
0
;
snd_pcm_period_elapsed
(
dpcm
->
substream
);
}
}
}
...
...
@@ -524,7 +548,7 @@ static snd_pcm_uframes_t loopback_pointer(struct snd_pcm_substream *substream)
static
struct
snd_pcm_hardware
loopback_pcm_hardware
=
{
.
info
=
(
SNDRV_PCM_INFO_INTERLEAVED
|
SNDRV_PCM_INFO_MMAP
|
SNDRV_PCM_INFO_MMAP_VALID
),
SNDRV_PCM_INFO_MMAP_VALID
|
SNDRV_PCM_INFO_PAUSE
),
.
formats
=
(
SNDRV_PCM_FMTBIT_S16_LE
|
SNDRV_PCM_FMTBIT_S16_BE
|
SNDRV_PCM_FMTBIT_S32_LE
|
SNDRV_PCM_FMTBIT_S32_BE
|
SNDRV_PCM_FMTBIT_FLOAT_LE
|
SNDRV_PCM_FMTBIT_FLOAT_BE
),
...
...
@@ -1011,6 +1035,87 @@ static int __devinit loopback_mixer_new(struct loopback *loopback, int notify)
return
0
;
}
#ifdef CONFIG_PROC_FS
static
void
print_dpcm_info
(
struct
snd_info_buffer
*
buffer
,
struct
loopback_pcm
*
dpcm
,
const
char
*
id
)
{
snd_iprintf
(
buffer
,
" %s
\n
"
,
id
);
if
(
dpcm
==
NULL
)
{
snd_iprintf
(
buffer
,
" inactive
\n
"
);
return
;
}
snd_iprintf
(
buffer
,
" buffer_size:
\t
%u
\n
"
,
dpcm
->
pcm_buffer_size
);
snd_iprintf
(
buffer
,
" buffer_pos:
\t\t
%u
\n
"
,
dpcm
->
buf_pos
);
snd_iprintf
(
buffer
,
" silent_size:
\t
%u
\n
"
,
dpcm
->
silent_size
);
snd_iprintf
(
buffer
,
" period_size:
\t
%u
\n
"
,
dpcm
->
pcm_period_size
);
snd_iprintf
(
buffer
,
" bytes_per_sec:
\t
%u
\n
"
,
dpcm
->
pcm_bps
);
snd_iprintf
(
buffer
,
" sample_align:
\t
%u
\n
"
,
dpcm
->
pcm_salign
);
snd_iprintf
(
buffer
,
" rate_shift:
\t\t
%u
\n
"
,
dpcm
->
pcm_rate_shift
);
snd_iprintf
(
buffer
,
" update_pending:
\t
%u
\n
"
,
dpcm
->
period_update_pending
);
snd_iprintf
(
buffer
,
" irq_pos:
\t\t
%u
\n
"
,
dpcm
->
irq_pos
);
snd_iprintf
(
buffer
,
" period_frac:
\t
%u
\n
"
,
dpcm
->
period_size_frac
);
snd_iprintf
(
buffer
,
" last_jiffies:
\t
%lu (%lu)
\n
"
,
dpcm
->
last_jiffies
,
jiffies
);
snd_iprintf
(
buffer
,
" timer_expires:
\t
%lu
\n
"
,
dpcm
->
timer
.
expires
);
}
static
void
print_substream_info
(
struct
snd_info_buffer
*
buffer
,
struct
loopback
*
loopback
,
int
sub
,
int
num
)
{
struct
loopback_cable
*
cable
=
loopback
->
cables
[
sub
][
num
];
snd_iprintf
(
buffer
,
"Cable %i substream %i:
\n
"
,
num
,
sub
);
if
(
cable
==
NULL
)
{
snd_iprintf
(
buffer
,
" inactive
\n
"
);
return
;
}
snd_iprintf
(
buffer
,
" valid: %u
\n
"
,
cable
->
valid
);
snd_iprintf
(
buffer
,
" running: %u
\n
"
,
cable
->
running
);
snd_iprintf
(
buffer
,
" pause: %u
\n
"
,
cable
->
pause
);
print_dpcm_info
(
buffer
,
cable
->
streams
[
0
],
"Playback"
);
print_dpcm_info
(
buffer
,
cable
->
streams
[
1
],
"Capture"
);
}
static
void
print_cable_info
(
struct
snd_info_entry
*
entry
,
struct
snd_info_buffer
*
buffer
)
{
struct
loopback
*
loopback
=
entry
->
private_data
;
int
sub
,
num
;
mutex_lock
(
&
loopback
->
cable_lock
);
num
=
entry
->
name
[
strlen
(
entry
->
name
)
-
1
];
num
=
num
==
'0'
?
0
:
1
;
for
(
sub
=
0
;
sub
<
MAX_PCM_SUBSTREAMS
;
sub
++
)
print_substream_info
(
buffer
,
loopback
,
sub
,
num
);
mutex_unlock
(
&
loopback
->
cable_lock
);
}
static
int
__devinit
loopback_proc_new
(
struct
loopback
*
loopback
,
int
cidx
)
{
char
name
[
32
];
struct
snd_info_entry
*
entry
;
int
err
;
snprintf
(
name
,
sizeof
(
name
),
"cable#%d"
,
cidx
);
err
=
snd_card_proc_new
(
loopback
->
card
,
name
,
&
entry
);
if
(
err
<
0
)
return
err
;
snd_info_set_text_ops
(
entry
,
loopback
,
print_cable_info
);
return
0
;
}
#else
/* !CONFIG_PROC_FS */
#define loopback_proc_new(loopback, cidx) do { } while (0)
#endif
static
int
__devinit
loopback_probe
(
struct
platform_device
*
devptr
)
{
struct
snd_card
*
card
;
...
...
@@ -1041,6 +1146,8 @@ static int __devinit loopback_probe(struct platform_device *devptr)
err
=
loopback_mixer_new
(
loopback
,
pcm_notify
[
dev
]
?
1
:
0
);
if
(
err
<
0
)
goto
__nodev
;
loopback_proc_new
(
loopback
,
0
);
loopback_proc_new
(
loopback
,
1
);
strcpy
(
card
->
driver
,
"Loopback"
);
strcpy
(
card
->
shortname
,
"Loopback"
);
sprintf
(
card
->
longname
,
"Loopback %i"
,
dev
+
1
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录