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
Kirill Smelkov
linux
Commits
1a6f11e0
Commit
1a6f11e0
authored
Jan 05, 2008
by
Mauro Carvalho Chehab
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
V4L/DVB (6950): Lindent em28xx-audio.c
Signed-off-by:
Mauro Carvalho Chehab
<
mchehab@infradead.org
>
parent
a52932b4
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
197 additions
and
176 deletions
+197
-176
drivers/media/video/em28xx/em28xx-audio.c
drivers/media/video/em28xx/em28xx-audio.c
+197
-176
No files found.
drivers/media/video/em28xx/em28xx-audio.c
View file @
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
)
...
...
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