Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
1a6f11e0
cloud-kernel
项目概览
openanolis
/
cloud-kernel
大约 1 年 前同步成功
通知
158
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看板
提交
1a6f11e0
编写于
1月 05, 2008
作者:
M
Mauro Carvalho Chehab
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
V4L/DVB (6950): Lindent em28xx-audio.c
Signed-off-by:
N
Mauro Carvalho Chehab
<
mchehab@infradead.org
>
上级
a52932b4
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
197 addition
and
176 deletion
+197
-176
drivers/media/video/em28xx/em28xx-audio.c
drivers/media/video/em28xx/em28xx-audio.c
+197
-176
未找到文件。
drivers/media/video/em28xx/em28xx-audio.c
浏览文件 @
1a6f11e0
...
...
@@ -44,37 +44,39 @@
#include "em28xx.h"
static
int
index
[
SNDRV_CARDS
]
=
SNDRV_DEFAULT_IDX
;
static
int
em28xx_cmd
(
struct
em28xx
*
dev
,
int
cmd
,
int
arg
);
static
int
em28xx_cmd
(
struct
em28xx
*
dev
,
int
cmd
,
int
arg
);
static
int
snd_pcm_alloc_vmalloc_buffer
(
struct
snd_pcm_substream
*
subs
,
size_t
size
)
static
int
snd_pcm_alloc_vmalloc_buffer
(
struct
snd_pcm_substream
*
subs
,
size_t
size
)
{
struct
snd_pcm_runtime
*
runtime
=
subs
->
runtime
;
if
(
runtime
->
dma_area
)
{
if
(
runtime
->
dma_bytes
>
size
)
if
(
runtime
->
dma_area
)
{
if
(
runtime
->
dma_bytes
>
size
)
return
0
;
vfree
(
runtime
->
dma_area
);
}
runtime
->
dma_area
=
vmalloc
(
size
);
if
(
!
runtime
->
dma_area
)
if
(
!
runtime
->
dma_area
)
return
-
ENOMEM
;
runtime
->
dma_bytes
=
size
;
return
0
;
}
static
struct
snd_pcm_hardware
snd_em28xx_hw_capture
=
{
.
info
=
SNDRV_PCM_INFO_BLOCK_TRANSFER
|
SNDRV_PCM_INFO_MMAP
|
SNDRV_PCM_INFO_INTERLEAVED
|
SNDRV_PCM_INFO_MMAP_VALID
,
.
info
=
SNDRV_PCM_INFO_BLOCK_TRANSFER
|
SNDRV_PCM_INFO_MMAP
|
SNDRV_PCM_INFO_INTERLEAVED
|
SNDRV_PCM_INFO_MMAP_VALID
,
.
formats
=
SNDRV_PCM_FMTBIT_S16_LE
,
.
rates
=
SNDRV_PCM_RATE_CONTINUOUS
|
SNDRV_PCM_RATE_KNOT
,
.
rate_min
=
48000
,
.
rate_max
=
48000
,
.
channels_min
=
2
,
.
channels_max
=
2
,
.
buffer_bytes_max
=
62720
*
8
,
/* just about the value in usbaudio.c */
.
period_bytes_min
=
64
,
//12544/2,
.
buffer_bytes_max
=
62720
*
8
,
/* just about the value in usbaudio.c */
.
period_bytes_min
=
64
,
//12544/2,
.
period_bytes_max
=
12544
,
.
periods_min
=
2
,
.
periods_max
=
98
,
//12544,
.
periods_max
=
98
,
//12544,
};
static
int
snd_em28xx_capture_open
(
struct
snd_pcm_substream
*
substream
)
...
...
@@ -84,66 +86,68 @@ static int snd_em28xx_capture_open(struct snd_pcm_substream *substream)
struct
em28xx
*
dev
=
snd_pcm_substream_chip
(
substream
);
struct
snd_pcm_runtime
*
runtime
=
substream
->
runtime
;
printk
(
"opening radio device and trying to acquire exclusive lock
\n
"
);
switch
(
dev
->
mode
){
case
TUNER_STUB_DVBC_TV
:
case
TUNER_STUB_DVBT_TV
:
case
TUNER_STUB_ATSC_TV
:
/* digital has no support for analog audio */
if
(
ret
!=
0
)
{
printk
(
"device is already in use by DVB-T
\n
"
);
return
-
EINVAL
;
}
else
{
struct
v4l2_tuner
tuner
;
printk
(
"switching device to FM mode
\n
"
);
mode
=
TUNER_STUB_RADIO
;
memset
(
&
tuner
,
0x0
,
sizeof
(
struct
v4l2_tuner
));
tuner
.
type
=
V4L2_TUNER_RADIO
;
/* enable GPIO for analog TV */
dev
->
em28xx_gpio_control
(
dev
,
EM28XX_MODE
,
(
void
*
)
mode
);
dev
->
mode
=
mode
;
/* upload firmware */
tuner_run_cmd
(
dev
->
tobj
,
TUNER_CMD_INIT
,
(
void
*
)
mode
);
/* required for devices which have kerneldriver dependencies */
// em28xx_config(dev);
// em28xx_config_i2c(dev);
/* this is moreover to switch the decoder to FM */
em28xx_i2c_call_clients
(
dev
,
VIDIOC_S_TUNER
,
&
tuner
);
dev
->
em28xx_write_regs
(
dev
,
0x0f
,
"
\x87
"
,
1
);
ret
=
dev
->
em28xx_acquire
(
dev
,
EM28XX_RADIO
,
1
);
em28xx_i2c_call_clients
(
dev
,
VIDIOC_INT_RESET
,
0
);
/* TODO switch to FM mode */
printk
(
"em28xx-audio: %d mode
\n
"
,
mode
);
tuner_run_cmd
(
dev
->
tobj
,
TUNER_CMD_G_MODE
,
&
mode
);
printk
(
"retrieved mode from tuner: %d
\n
"
,
mode
);
}
break
;
case
TUNER_STUB_ANALOG_TV
:
printk
(
"em28xx-audio: device is currently in analog TV mode
\n
"
);
/* unmute by default */
dev
->
em28xx_write_regs
(
dev
,
0x0f
,
"
\x87
"
,
1
);
break
;
case
TUNER_STUB_RADIO
:
/* check current mode and put a hard lock onto it */
printk
(
"em28xx-audio: device is currently in analogue FM mode
\n
"
);
/* unmute by default here */
dev
->
em28xx_write_regs
(
dev
,
0x0f
,
"
\x87
"
,
1
);
ret
=
dev
->
em28xx_acquire
(
dev
,
EM28XX_RADIO
,
1
);
if
(
ret
==
0
)
printk
(
"device is locked in fmradio mode now
\n
"
);
break
;
default:
printk
(
"em28xx-audio: unhandled mode %d
\n
"
,
dev
->
mode
);
switch
(
dev
->
mode
)
{
case
TUNER_STUB_DVBC_TV
:
case
TUNER_STUB_DVBT_TV
:
case
TUNER_STUB_ATSC_TV
:
/* digital has no support for analog audio */
if
(
ret
!=
0
)
{
printk
(
"device is already in use by DVB-T
\n
"
);
return
-
EINVAL
;
}
else
{
struct
v4l2_tuner
tuner
;
printk
(
"switching device to FM mode
\n
"
);
mode
=
TUNER_STUB_RADIO
;
memset
(
&
tuner
,
0x0
,
sizeof
(
struct
v4l2_tuner
));
tuner
.
type
=
V4L2_TUNER_RADIO
;
/* enable GPIO for analog TV */
dev
->
em28xx_gpio_control
(
dev
,
EM28XX_MODE
,
(
void
*
)
mode
);
dev
->
mode
=
mode
;
/* upload firmware */
tuner_run_cmd
(
dev
->
tobj
,
TUNER_CMD_INIT
,
(
void
*
)
mode
);
/* required for devices which have kerneldriver dependencies */
// em28xx_config(dev);
// em28xx_config_i2c(dev);
/* this is moreover to switch the decoder to FM */
em28xx_i2c_call_clients
(
dev
,
VIDIOC_S_TUNER
,
&
tuner
);
dev
->
em28xx_write_regs
(
dev
,
0x0f
,
"
\x87
"
,
1
);
ret
=
dev
->
em28xx_acquire
(
dev
,
EM28XX_RADIO
,
1
);
em28xx_i2c_call_clients
(
dev
,
VIDIOC_INT_RESET
,
0
);
/* TODO switch to FM mode */
printk
(
"em28xx-audio: %d mode
\n
"
,
mode
);
tuner_run_cmd
(
dev
->
tobj
,
TUNER_CMD_G_MODE
,
&
mode
);
printk
(
"retrieved mode from tuner: %d
\n
"
,
mode
);
}
break
;
case
TUNER_STUB_ANALOG_TV
:
printk
(
"em28xx-audio: device is currently in analog TV mode
\n
"
);
/* unmute by default */
dev
->
em28xx_write_regs
(
dev
,
0x0f
,
"
\x87
"
,
1
);
break
;
case
TUNER_STUB_RADIO
:
/* check current mode and put a hard lock onto it */
printk
(
"em28xx-audio: device is currently in analogue FM mode
\n
"
);
/* unmute by default here */
dev
->
em28xx_write_regs
(
dev
,
0x0f
,
"
\x87
"
,
1
);
ret
=
dev
->
em28xx_acquire
(
dev
,
EM28XX_RADIO
,
1
);
if
(
ret
==
0
)
printk
(
"device is locked in fmradio mode now
\n
"
);
break
;
default:
printk
(
"em28xx-audio: unhandled mode %d
\n
"
,
dev
->
mode
);
}
runtime
->
hw
=
snd_em28xx_hw_capture
;
if
(
dev
->
alt
==
0
&&
dev
->
adev
->
users
==
0
)
{
if
(
dev
->
alt
==
0
&&
dev
->
adev
->
users
==
0
)
{
int
errCode
;
dev
->
alt
=
7
;
errCode
=
usb_set_interface
(
dev
->
udev
,
0
,
7
);
...
...
@@ -163,48 +167,51 @@ static int snd_em28xx_pcm_close(struct snd_pcm_substream *substream)
dev
->
adev
->
users
--
;
/* decrease audio reference */
switch
(
dev
->
mode
)
{
case
TUNER_STUB_ANALOG_TV
:
amode
=
EM28XX_VIDEO
;
break
;
case
TUNER_STUB_RADIO
:
amode
=
EM28XX_RADIO
;
break
;
default:
printk
(
"invalid mode: %d
\n
"
,
dev
->
mode
);
break
;
switch
(
dev
->
mode
)
{
case
TUNER_STUB_ANALOG_TV
:
amode
=
EM28XX_VIDEO
;
break
;
case
TUNER_STUB_RADIO
:
amode
=
EM28XX_RADIO
;
break
;
default:
printk
(
"invalid mode: %d
\n
"
,
dev
->
mode
);
break
;
}
dev
->
em28xx_acquire
(
dev
,
amode
,
0
);
dev
->
em28xx_acquire
(
dev
,
amode
,
0
);
if
(
dev
->
adev
->
users
==
0
&&
dev
->
adev
->
shutdown
==
1
)
{
printk
(
"audio users: %d
\n
"
,
dev
->
adev
->
users
);
if
(
dev
->
adev
->
users
==
0
&&
dev
->
adev
->
shutdown
==
1
)
{
printk
(
"audio users: %d
\n
"
,
dev
->
adev
->
users
);
printk
(
"disabling audio stream!
\n
"
);
dev
->
adev
->
shutdown
=
0
;
printk
(
"released lock
\n
"
);
em28xx_cmd
(
dev
,
EM28XX_CAPTURE_STREAM_EN
,
0
);
em28xx_cmd
(
dev
,
EM28XX_CAPTURE_STREAM_EN
,
0
);
}
return
0
;
}
static
int
snd_em28xx_hw_capture_params
(
struct
snd_pcm_substream
*
substream
,
struct
snd_pcm_hw_params
*
hw_params
)
static
int
snd_em28xx_hw_capture_params
(
struct
snd_pcm_substream
*
substream
,
struct
snd_pcm_hw_params
*
hw_params
)
{
unsigned
int
channels
,
rate
,
format
;
int
ret
;
ret
=
snd_pcm_alloc_vmalloc_buffer
(
substream
,
params_buffer_bytes
(
hw_params
));
ret
=
snd_pcm_alloc_vmalloc_buffer
(
substream
,
params_buffer_bytes
(
hw_params
));
format
=
params_format
(
hw_params
);
rate
=
params_rate
(
hw_params
);
channels
=
params_channels
(
hw_params
);
/* TODO: set up em28xx audio chip to deliver the correct audio format, current default is 48000hz multiplexed => 96000hz mono
which shouldn't matter since analogue TV only supports mono*/
which shouldn't matter since analogue TV only supports mono
*/
return
0
;
}
static
int
snd_em28xx_hw_capture_free
(
struct
snd_pcm_substream
*
substream
)
{
struct
em28xx
*
dev
=
snd_pcm_substream_chip
(
substream
);
if
(
dev
->
adev
->
capture_stream
==
STREAM_ON
)
{
em28xx_cmd
(
dev
,
EM28XX_CAPTURE_STREAM_EN
,
0
);
if
(
dev
->
adev
->
capture_stream
==
STREAM_ON
)
{
em28xx_cmd
(
dev
,
EM28XX_CAPTURE_STREAM_EN
,
0
);
}
return
0
;
}
...
...
@@ -214,24 +221,25 @@ static int snd_em28xx_prepare(struct snd_pcm_substream *substream)
return
0
;
}
static
int
snd_em28xx_capture_trigger
(
struct
snd_pcm_substream
*
substream
,
int
cmd
)
static
int
snd_em28xx_capture_trigger
(
struct
snd_pcm_substream
*
substream
,
int
cmd
)
{
struct
em28xx
*
dev
=
snd_pcm_substream_chip
(
substream
);
switch
(
cmd
)
{
case
SNDRV_PCM_TRIGGER_START
:
em28xx_cmd
(
dev
,
EM28XX_CAPTURE_STREAM_EN
,
1
);
return
0
;
case
SNDRV_PCM_TRIGGER_STOP
:
dev
->
adev
->
shutdown
=
1
;
return
0
;
default:
return
-
EINVAL
;
switch
(
cmd
)
{
case
SNDRV_PCM_TRIGGER_START
:
em28xx_cmd
(
dev
,
EM28XX_CAPTURE_STREAM_EN
,
1
);
return
0
;
case
SNDRV_PCM_TRIGGER_STOP
:
dev
->
adev
->
shutdown
=
1
;
return
0
;
default:
return
-
EINVAL
;
}
}
static
void
em28xx_audio_isocirq
(
struct
urb
*
urb
)
{
struct
em28xx
*
dev
=
urb
->
context
;
struct
em28xx
*
dev
=
urb
->
context
;
int
i
;
unsigned
int
oldptr
;
unsigned
long
flags
;
...
...
@@ -241,50 +249,61 @@ static void em28xx_audio_isocirq(struct urb *urb)
unsigned
int
stride
;
struct
snd_pcm_substream
*
substream
;
struct
snd_pcm_runtime
*
runtime
;
if
(
dev
->
adev
->
capture_pcm_substream
)
{
substream
=
dev
->
adev
->
capture_pcm_substream
;
runtime
=
substream
->
runtime
;
if
(
dev
->
adev
->
capture_pcm_substream
)
{
substream
=
dev
->
adev
->
capture_pcm_substream
;
runtime
=
substream
->
runtime
;
stride
=
runtime
->
frame_bits
>>
3
;
for
(
i
=
0
;
i
<
urb
->
number_of_packets
;
i
++
){
int
length
=
urb
->
iso_frame_desc
[
i
].
actual_length
/
stride
;
cp
=
(
unsigned
char
*
)
urb
->
transfer_buffer
+
urb
->
iso_frame_desc
[
i
].
offset
;
for
(
i
=
0
;
i
<
urb
->
number_of_packets
;
i
++
)
{
int
length
=
urb
->
iso_frame_desc
[
i
].
actual_length
/
stride
;
cp
=
(
unsigned
char
*
)
urb
->
transfer_buffer
+
urb
->
iso_frame_desc
[
i
].
offset
;
if
(
!
length
)
if
(
!
length
)
continue
;
spin_lock_irqsave
(
&
dev
->
adev
->
slock
,
flags
);
oldptr
=
dev
->
adev
->
hwptr_done_capture
;
dev
->
adev
->
hwptr_done_capture
+=
length
;
if
(
dev
->
adev
->
hwptr_done_capture
>=
runtime
->
buffer_size
)
dev
->
adev
->
hwptr_done_capture
-=
runtime
->
buffer_size
;
dev
->
adev
->
hwptr_done_capture
+=
length
;
if
(
dev
->
adev
->
hwptr_done_capture
>=
runtime
->
buffer_size
)
dev
->
adev
->
hwptr_done_capture
-=
runtime
->
buffer_size
;
dev
->
adev
->
capture_transfer_done
+=
length
;
if
(
dev
->
adev
->
capture_transfer_done
>=
runtime
->
period_size
){
dev
->
adev
->
capture_transfer_done
-=
runtime
->
period_size
;
period_elapsed
=
1
;
if
(
dev
->
adev
->
capture_transfer_done
>=
runtime
->
period_size
)
{
dev
->
adev
->
capture_transfer_done
-=
runtime
->
period_size
;
period_elapsed
=
1
;
}
spin_unlock_irqrestore
(
&
dev
->
adev
->
slock
,
flags
);
if
(
oldptr
+
length
>=
runtime
->
buffer_size
){
unsigned
int
cnt
=
runtime
->
buffer_size
-
oldptr
-
1
;
memcpy
(
runtime
->
dma_area
+
oldptr
*
stride
,
cp
,
cnt
*
stride
);
memcpy
(
runtime
->
dma_area
,
cp
+
cnt
,
length
*
stride
-
cnt
*
stride
);
if
(
oldptr
+
length
>=
runtime
->
buffer_size
)
{
unsigned
int
cnt
=
runtime
->
buffer_size
-
oldptr
-
1
;
memcpy
(
runtime
->
dma_area
+
oldptr
*
stride
,
cp
,
cnt
*
stride
);
memcpy
(
runtime
->
dma_area
,
cp
+
cnt
,
length
*
stride
-
cnt
*
stride
);
}
else
{
memcpy
(
runtime
->
dma_area
+
oldptr
*
stride
,
cp
,
length
*
stride
);
memcpy
(
runtime
->
dma_area
+
oldptr
*
stride
,
cp
,
length
*
stride
);
}
}
if
(
period_elapsed
)
{
if
(
period_elapsed
)
{
snd_pcm_period_elapsed
(
substream
);
}
}
urb
->
status
=
0
;
if
(
dev
->
adev
->
shutdown
)
if
(
dev
->
adev
->
shutdown
)
return
;
if
((
status
=
usb_submit_urb
(
urb
,
GFP_ATOMIC
))){
em28xx_errdev
(
"resubmit of audio urb failed (error=%i)
\n
"
,
status
);
if
((
status
=
usb_submit_urb
(
urb
,
GFP_ATOMIC
)))
{
em28xx_errdev
(
"resubmit of audio urb failed (error=%i)
\n
"
,
status
);
}
return
;
}
...
...
@@ -292,10 +311,10 @@ static void em28xx_audio_isocirq(struct urb *urb)
static
int
em28xx_isoc_audio_deinit
(
struct
em28xx
*
dev
)
{
int
i
;
for
(
i
=
0
;
i
<
EM28XX_AUDIO_BUFS
;
i
++
)
{
for
(
i
=
0
;
i
<
EM28XX_AUDIO_BUFS
;
i
++
)
{
usb_kill_urb
(
dev
->
adev
->
urb
[
i
]);
usb_free_urb
(
dev
->
adev
->
urb
[
i
]);
dev
->
adev
->
urb
[
i
]
=
NULL
;
dev
->
adev
->
urb
[
i
]
=
NULL
;
}
return
0
;
}
...
...
@@ -304,40 +323,42 @@ static int em28xx_init_audio_isoc(struct em28xx *dev)
{
int
i
;
int
errCode
;
const
int
sb_size
=
EM28XX_NUM_AUDIO_PACKETS
*
EM28XX_AUDIO_MAX_PACKET_SIZE
;
const
int
sb_size
=
EM28XX_NUM_AUDIO_PACKETS
*
EM28XX_AUDIO_MAX_PACKET_SIZE
;
for
(
i
=
0
;
i
<
EM28XX_AUDIO_BUFS
;
i
++
){
for
(
i
=
0
;
i
<
EM28XX_AUDIO_BUFS
;
i
++
)
{
struct
urb
*
urb
;
int
j
,
k
;
dev
->
adev
->
transfer_buffer
[
i
]
=
kmalloc
(
sb_size
,
GFP_ATOMIC
);
if
(
!
dev
->
adev
->
transfer_buffer
[
i
])
{
int
j
,
k
;
dev
->
adev
->
transfer_buffer
[
i
]
=
kmalloc
(
sb_size
,
GFP_ATOMIC
);
if
(
!
dev
->
adev
->
transfer_buffer
[
i
])
{
return
-
ENOMEM
;
}
memset
(
dev
->
adev
->
transfer_buffer
[
i
],
0x80
,
sb_size
);
urb
=
usb_alloc_urb
(
EM28XX_NUM_AUDIO_PACKETS
,
GFP_ATOMIC
);
if
(
urb
)
{
urb
->
dev
=
dev
->
udev
;
urb
->
context
=
dev
;
urb
->
pipe
=
usb_rcvisocpipe
(
dev
->
udev
,
0x83
);
memset
(
dev
->
adev
->
transfer_buffer
[
i
],
0x80
,
sb_size
);
urb
=
usb_alloc_urb
(
EM28XX_NUM_AUDIO_PACKETS
,
GFP_ATOMIC
);
if
(
urb
)
{
urb
->
dev
=
dev
->
udev
;
urb
->
context
=
dev
;
urb
->
pipe
=
usb_rcvisocpipe
(
dev
->
udev
,
0x83
);
urb
->
transfer_flags
=
URB_ISO_ASAP
;
urb
->
transfer_buffer
=
dev
->
adev
->
transfer_buffer
[
i
];
urb
->
interval
=
1
;
urb
->
interval
=
1
;
urb
->
complete
=
em28xx_audio_isocirq
;
urb
->
number_of_packets
=
EM28XX_NUM_AUDIO_PACKETS
;
urb
->
transfer_buffer_length
=
sb_size
;
for
(
j
=
k
=
0
;
j
<
EM28XX_NUM_AUDIO_PACKETS
;
j
++
,
k
+=
EM28XX_AUDIO_MAX_PACKET_SIZE
){
for
(
j
=
k
=
0
;
j
<
EM28XX_NUM_AUDIO_PACKETS
;
j
++
,
k
+=
EM28XX_AUDIO_MAX_PACKET_SIZE
)
{
urb
->
iso_frame_desc
[
j
].
offset
=
k
;
urb
->
iso_frame_desc
[
j
].
length
=
EM28XX_AUDIO_MAX_PACKET_SIZE
;
urb
->
iso_frame_desc
[
j
].
length
=
EM28XX_AUDIO_MAX_PACKET_SIZE
;
}
dev
->
adev
->
urb
[
i
]
=
urb
;
dev
->
adev
->
urb
[
i
]
=
urb
;
}
else
{
return
-
ENOMEM
;
}
}
for
(
i
=
0
;
i
<
EM28XX_AUDIO_BUFS
;
i
++
)
{
for
(
i
=
0
;
i
<
EM28XX_AUDIO_BUFS
;
i
++
)
{
errCode
=
usb_submit_urb
(
dev
->
adev
->
urb
[
i
],
GFP_ATOMIC
);
if
(
errCode
){
if
(
errCode
)
{
em28xx_isoc_audio_deinit
(
dev
);
return
errCode
;
}
...
...
@@ -345,27 +366,28 @@ static int em28xx_init_audio_isoc(struct em28xx *dev)
return
0
;
}
static
int
em28xx_cmd
(
struct
em28xx
*
dev
,
int
cmd
,
int
arg
)
static
int
em28xx_cmd
(
struct
em28xx
*
dev
,
int
cmd
,
int
arg
)
{
switch
(
cmd
){
case
EM28XX_CAPTURE_STREAM_EN
:
if
(
dev
->
adev
->
capture_stream
==
STREAM_OFF
&&
arg
==
1
){
dev
->
adev
->
capture_stream
=
STREAM_ON
;
em28xx_init_audio_isoc
(
dev
);
}
else
if
(
dev
->
adev
->
capture_stream
==
STREAM_ON
&&
arg
==
0
){
dev
->
adev
->
capture_stream
=
STREAM_OFF
;
em28xx_isoc_audio_deinit
(
dev
);
}
else
{
printk
(
"An underrun occured very likely... ignoring it
\n
"
);
}
return
0
;
default:
return
-
EINVAL
;
switch
(
cmd
)
{
case
EM28XX_CAPTURE_STREAM_EN
:
if
(
dev
->
adev
->
capture_stream
==
STREAM_OFF
&&
arg
==
1
)
{
dev
->
adev
->
capture_stream
=
STREAM_ON
;
em28xx_init_audio_isoc
(
dev
);
}
else
if
(
dev
->
adev
->
capture_stream
==
STREAM_ON
&&
arg
==
0
)
{
dev
->
adev
->
capture_stream
=
STREAM_OFF
;
em28xx_isoc_audio_deinit
(
dev
);
}
else
{
printk
(
"An underrun occured very likely... ignoring it
\n
"
);
}
return
0
;
default:
return
-
EINVAL
;
}
}
static
snd_pcm_uframes_t
snd_em28xx_capture_pointer
(
struct
snd_pcm_substream
*
substream
)
static
snd_pcm_uframes_t
snd_em28xx_capture_pointer
(
struct
snd_pcm_substream
*
substream
)
{
struct
em28xx
*
dev
;
snd_pcm_uframes_t
hwptr_done
;
...
...
@@ -393,7 +415,6 @@ static struct snd_pcm_ops snd_em28xx_pcm_capture = {
.
page
=
snd_pcm_get_vmalloc_page
,
};
static
int
em28xx_audio_init
(
struct
em28xx
*
dev
)
{
struct
em28xx_audio
*
adev
;
...
...
@@ -404,54 +425,54 @@ static int em28xx_audio_init(struct em28xx *dev)
int
err
;
printk
(
"em28xx-audio.c: probing for em28x1 non standard usbaudio
\n
"
);
printk
(
"em28xx-audio.c: Copyright (C) 2006 Markus Rechberger
\n
"
);
adev
=
kzalloc
(
sizeof
(
*
adev
),
GFP_KERNEL
);
if
(
!
adev
)
{
adev
=
kzalloc
(
sizeof
(
*
adev
),
GFP_KERNEL
);
if
(
!
adev
)
{
printk
(
"em28xx-audio.c: out of memory
\n
"
);
return
-
1
;
}
card
=
snd_card_new
(
index
[
devnr
],
"Em28xx Audio"
,
THIS_MODULE
,
0
);
if
(
card
==
NULL
)
{
card
=
snd_card_new
(
index
[
devnr
],
"Em28xx Audio"
,
THIS_MODULE
,
0
);
if
(
card
==
NULL
)
{
kfree
(
adev
);
return
-
ENOMEM
;
}
spin_lock_init
(
&
adev
->
slock
);
ret
=
snd_pcm_new
(
card
,
"Em28xx Audio"
,
0
,
0
,
1
,
&
pcm
);
ret
=
snd_pcm_new
(
card
,
"Em28xx Audio"
,
0
,
0
,
1
,
&
pcm
);
snd_pcm_set_ops
(
pcm
,
SNDRV_PCM_STREAM_CAPTURE
,
&
snd_em28xx_pcm_capture
);
pcm
->
info_flags
=
0
;
pcm
->
private_data
=
dev
;
strcpy
(
pcm
->
name
,
"Empia 28xx Capture"
);
strcpy
(
pcm
->
name
,
"Empia 28xx Capture"
);
strcpy
(
card
->
driver
,
"Empia Em28xx Audio"
);
strcpy
(
card
->
shortname
,
"Em28xx Audio"
);
strcpy
(
card
->
longname
,
"Empia Em28xx Audio"
);
strcpy
(
card
->
longname
,
"Empia Em28xx Audio"
);
if
((
err
=
snd_card_register
(
card
))
<
0
)
{
if
((
err
=
snd_card_register
(
card
))
<
0
)
{
snd_card_free
(
card
);
return
-
ENOMEM
;
}
adev
->
sndcard
=
card
;
adev
->
udev
=
dev
->
udev
;
dev
->
adev
=
adev
;
adev
->
sndcard
=
card
;
adev
->
udev
=
dev
->
udev
;
dev
->
adev
=
adev
;
return
0
;
}
static
int
em28xx_audio_fini
(
struct
em28xx
*
dev
)
{
if
(
dev
==
NULL
)
if
(
dev
==
NULL
)
return
0
;
if
(
dev
->
adev
)
{
if
(
dev
->
adev
)
{
snd_card_free
(
dev
->
adev
->
sndcard
);
kfree
(
dev
->
adev
);
dev
->
adev
=
NULL
;
dev
->
adev
=
NULL
;
}
return
0
;
}
static
struct
em28xx_ops
audio_ops
=
{
.
id
=
EM28XX_AUDIO
,
.
name
=
"Em28xx Audio Extension"
,
.
init
=
em28xx_audio_init
,
.
fini
=
em28xx_audio_fini
,
.
id
=
EM28XX_AUDIO
,
.
name
=
"Em28xx Audio Extension"
,
.
init
=
em28xx_audio_init
,
.
fini
=
em28xx_audio_fini
,
};
static
int
__init
em28xx_alsa_register
(
void
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录