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
0f8f56c9
Commit
0f8f56c9
authored
May 03, 2011
by
Takashi Iwai
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ALSA: lola - Fix PCM stalls
Signed-off-by:
Takashi Iwai
<
tiwai@suse.de
>
parent
333ff397
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
74 additions
and
47 deletions
+74
-47
sound/pci/lola/lola.c
sound/pci/lola/lola.c
+13
-4
sound/pci/lola/lola.h
sound/pci/lola/lola.h
+1
-0
sound/pci/lola/lola_pcm.c
sound/pci/lola/lola_pcm.c
+60
-43
No files found.
sound/pci/lola/lola.c
View file @
0f8f56c9
...
...
@@ -73,6 +73,7 @@ static int corb_send_verb(struct lola *chip, unsigned int nid,
chip
->
last_data
=
data
;
chip
->
last_extdata
=
extdata
;
data
|=
(
nid
<<
20
)
|
(
verb
<<
8
);
spin_lock_irqsave
(
&
chip
->
reg_lock
,
flags
);
if
(
chip
->
rirb
.
cmds
<
LOLA_CORB_ENTRIES
-
1
)
{
unsigned
int
wp
=
chip
->
corb
.
wp
+
1
;
...
...
@@ -338,8 +339,6 @@ static int setup_corb_rirb(struct lola *chip)
chip
->
corb
.
buf
=
(
u32
*
)
chip
->
rb
.
area
;
chip
->
rirb
.
addr
=
chip
->
rb
.
addr
+
2048
;
chip
->
rirb
.
buf
=
(
u32
*
)(
chip
->
rb
.
area
+
2048
);
lola_writel
(
chip
,
BAR0
,
CORBLBASE
,
(
u32
)
chip
->
corb
.
addr
);
lola_writel
(
chip
,
BAR0
,
CORBUBASE
,
upper_32_bits
(
chip
->
corb
.
addr
));
/* disable ringbuffer DMAs */
lola_writeb
(
chip
,
BAR0
,
RIRBCTL
,
0
);
...
...
@@ -496,6 +495,10 @@ static int lola_parse_tree(struct lola *chip)
if
(
!
chip
->
cold_reset
)
{
lola_reset_setups
(
chip
);
chip
->
cold_reset
=
1
;
}
else
{
/* set the granularity if it is not the default */
if
(
chip
->
granularity
!=
LOLA_GRANULARITY_MIN
)
lola_set_granularity
(
chip
,
chip
->
granularity
,
true
);
}
return
0
;
...
...
@@ -561,8 +564,14 @@ static int __devinit lola_create(struct snd_card *card, struct pci_dev *pci,
chip
->
pci
=
pci
;
chip
->
irq
=
-
1
;
chip
->
sample_rate_min
=
48000
;
chip
->
granularity
=
LOLA_GRANULARITY_MIN
;
/* below a sample_rate of 16kHz the analogue audio quality
* is NOT excellent
*/
chip
->
sample_rate_min
=
16000
;
/* for instance use always max granularity which is compatible
* with all sample rates
*/
chip
->
granularity
=
LOLA_GRANULARITY_MAX
;
err
=
pci_request_regions
(
pci
,
DRVNAME
);
if
(
err
<
0
)
{
...
...
sound/pci/lola/lola.h
View file @
0f8f56c9
...
...
@@ -305,6 +305,7 @@ struct lola_stream {
/* flags */
unsigned
int
opened
:
1
;
unsigned
int
prepared
:
1
;
unsigned
int
running
:
1
;
};
...
...
sound/pci/lola/lola_pcm.c
View file @
0f8f56c9
...
...
@@ -29,7 +29,6 @@
/* #define USE_SG_BUFFER */
#define LOLA_MAX_BDL_ENTRIES 8
#define LOLA_MAX_FRAG 8
#define LOLA_MAX_BUF_SIZE (1024*1024*1024)
#define LOLA_BDL_ENTRY_SIZE (16 * 16)
...
...
@@ -111,12 +110,6 @@ static void lola_stream_stop(struct lola *chip, struct lola_stream *str,
lola_stream_clear_pending_irq
(
chip
,
str
);
}
static
void
lola_stream_clear
(
struct
lola
*
chip
,
struct
lola_stream
*
str
)
{
lola_dsd_write
(
chip
,
str
->
dsd
,
CTL
,
0
);
lola_stream_clear_pending_irq
(
chip
,
str
);
}
static
void
wait_for_srst_clear
(
struct
lola
*
chip
,
struct
lola_stream
*
str
)
{
unsigned
long
end_time
=
jiffies
+
msecs_to_jiffies
(
200
);
...
...
@@ -130,22 +123,15 @@ static void wait_for_srst_clear(struct lola *chip, struct lola_stream *str)
printk
(
KERN_WARNING
SFX
"SRST not clear (stream %d)
\n
"
,
str
->
dsd
);
}
static
void
lola_stream_reset
(
struct
lola
*
chip
,
struct
lola_stream
*
str
)
static
int
lola_stream_wait_for_fifo
(
struct
lola
*
chip
,
struct
lola_stream
*
str
,
bool
ready
)
{
lola_dsd_write
(
chip
,
str
->
dsd
,
CTL
,
LOLA_DSD_CTL_SRST
);
wait_for_srst_clear
(
chip
,
str
);
lola_dsd_write
(
chip
,
str
->
dsd
,
LVI
,
0
);
lola_dsd_write
(
chip
,
str
->
dsd
,
BDPU
,
0
);
lola_dsd_write
(
chip
,
str
->
dsd
,
BDPL
,
0
);
}
static
int
lola_stream_wait_for_fifo_ready
(
struct
lola
*
chip
,
struct
lola_stream
*
str
)
{
unsigned
long
end_time
=
jiffies
+
msecs_to_jiffies
(
1000
);
unsigned
int
val
=
ready
?
LOLA_DSD_STS_FIFORDY
:
0
;
unsigned
long
end_time
=
jiffies
+
msecs_to_jiffies
(
200
);
while
(
time_before
(
jiffies
,
end_time
))
{
unsigned
int
val
=
lola_dsd_read
(
chip
,
str
->
dsd
,
STS
);
if
(
val
&
LOLA_DSD_STS_FIFORDY
)
unsigned
int
reg
=
lola_dsd_read
(
chip
,
str
->
dsd
,
STS
);
if
(
(
reg
&
LOLA_DSD_STS_FIFORDY
)
==
val
)
return
0
;
msleep
(
1
);
}
...
...
@@ -153,6 +139,23 @@ static int lola_stream_wait_for_fifo_ready(struct lola *chip,
return
-
EIO
;
}
static
void
lola_stream_reset
(
struct
lola
*
chip
,
struct
lola_stream
*
str
)
{
if
(
str
->
prepared
)
{
str
->
prepared
=
0
;
lola_dsd_write
(
chip
,
str
->
dsd
,
CTL
,
LOLA_DSD_CTL_IOCE
|
LOLA_DSD_CTL_DEIE
);
lola_stream_wait_for_fifo
(
chip
,
str
,
false
);
lola_stream_clear_pending_irq
(
chip
,
str
);
lola_dsd_write
(
chip
,
str
->
dsd
,
CTL
,
LOLA_DSD_CTL_SRST
);
lola_dsd_write
(
chip
,
str
->
dsd
,
LVI
,
0
);
lola_dsd_write
(
chip
,
str
->
dsd
,
BDPU
,
0
);
lola_dsd_write
(
chip
,
str
->
dsd
,
BDPL
,
0
);
wait_for_srst_clear
(
chip
,
str
);
}
}
static
struct
snd_pcm_hardware
lola_pcm_hw
=
{
.
info
=
(
SNDRV_PCM_INFO_MMAP
|
SNDRV_PCM_INFO_INTERLEAVED
|
...
...
@@ -163,16 +166,16 @@ static struct snd_pcm_hardware lola_pcm_hw = {
SNDRV_PCM_FMTBIT_S24_LE
|
SNDRV_PCM_FMTBIT_S32_LE
|
SNDRV_PCM_FMTBIT_FLOAT_LE
),
.
rates
=
SNDRV_PCM_RATE_
48
000
,
.
rate_min
=
4
8000
,
.
rate_max
=
48
000
,
.
rates
=
SNDRV_PCM_RATE_
8000_192
000
,
.
rate_min
=
8000
,
.
rate_max
=
192
000
,
.
channels_min
=
1
,
.
channels_max
=
2
,
.
buffer_bytes_max
=
LOLA_MAX_BUF_SIZE
,
.
period_bytes_min
=
128
,
.
period_bytes_max
=
LOLA_MAX_BUF_SIZE
/
2
,
.
periods_min
=
2
,
.
periods_max
=
LOLA_MAX_
FRAG
,
.
periods_max
=
LOLA_MAX_
BDL_ENTRIES
,
.
fifo_size
=
0
,
};
...
...
@@ -194,10 +197,13 @@ static int lola_pcm_open(struct snd_pcm_substream *substream)
runtime
->
hw
=
lola_pcm_hw
;
runtime
->
hw
.
channels_max
=
pcm
->
num_streams
-
str
->
index
;
snd_pcm_hw_constraint_integer
(
runtime
,
SNDRV_PCM_HW_PARAM_PERIODS
);
snd_pcm_hw_constraint_step
(
runtime
,
0
,
SNDRV_PCM_HW_PARAM_BUFFER_BYTES
,
128
);
snd_pcm_hw_constraint_step
(
runtime
,
0
,
SNDRV_PCM_HW_PARAM_PERIOD_BYTES
,
128
);
/* period size = multiple of chip->granularity (8, 16 or 32 frames)
* use LOLA_GRANULARITY_MAX = 32 for instance
*/
snd_pcm_hw_constraint_step
(
runtime
,
0
,
SNDRV_PCM_HW_PARAM_BUFFER_SIZE
,
LOLA_GRANULARITY_MAX
);
snd_pcm_hw_constraint_step
(
runtime
,
0
,
SNDRV_PCM_HW_PARAM_PERIOD_SIZE
,
LOLA_GRANULARITY_MAX
);
mutex_unlock
(
&
chip
->
open_mutex
);
return
0
;
}
...
...
@@ -383,16 +389,24 @@ static int lola_setup_controller(struct lola *chip, struct lola_pcm *pcm,
struct
lola_stream
*
str
)
{
dma_addr_t
bdl
;
if
(
str
->
prepared
)
return
-
EINVAL
;
/* set up BDL */
bdl
=
pcm
->
bdl
.
addr
+
LOLA_BDL_ENTRY_SIZE
*
str
->
index
;
lola_dsd_write
(
chip
,
str
->
dsd
,
BDPL
,
(
u32
)
bdl
);
lola_dsd_write
(
chip
,
str
->
dsd
,
BDPU
,
upper_32_bits
(
bdl
));
/* program the stream LVI (last valid index) of the BDL */
lola_dsd_write
(
chip
,
str
->
dsd
,
LVI
,
str
->
frags
-
1
);
lola_stream_stop
(
chip
,
str
,
lola_get_tstamp
(
chip
,
false
));
lola_stream_wait_for_fifo_ready
(
chip
,
str
);
lola_stream_clear_pending_irq
(
chip
,
str
);
return
0
;
lola_dsd_write
(
chip
,
str
->
dsd
,
CTL
,
LOLA_DSD_CTL_IOCE
|
LOLA_DSD_CTL_DEIE
|
LOLA_DSD_CTL_SRUN
);
str
->
prepared
=
1
;
return
lola_stream_wait_for_fifo
(
chip
,
str
,
true
);
}
static
int
lola_pcm_prepare
(
struct
snd_pcm_substream
*
substream
)
...
...
@@ -421,22 +435,25 @@ static int lola_pcm_prepare(struct snd_pcm_substream *substream)
period_bytes
=
snd_pcm_lib_period_bytes
(
substream
);
format_verb
=
lola_get_format_verb
(
substream
);
if
(
bufsize
!=
str
->
bufsize
||
period_bytes
!=
str
->
period_bytes
||
format_verb
!=
str
->
format_verb
)
{
str
->
bufsize
=
bufsize
;
str
->
period_bytes
=
period_bytes
;
str
->
format_verb
=
format_verb
;
err
=
lola_setup_periods
(
chip
,
pcm
,
substream
,
str
);
if
(
err
<
0
)
return
err
;
}
str
->
bufsize
=
bufsize
;
str
->
period_bytes
=
period_bytes
;
str
->
format_verb
=
format_verb
;
err
=
lola_setup_periods
(
chip
,
pcm
,
substream
,
str
);
if
(
err
<
0
)
return
err
;
err
=
lola_set_stream_config
(
chip
,
str
,
runtime
->
channels
);
if
(
err
<
0
)
return
err
;
return
lola_setup_controller
(
chip
,
pcm
,
str
);
err
=
lola_setup_controller
(
chip
,
pcm
,
str
);
if
(
err
<
0
)
{
lola_stream_reset
(
chip
,
str
);
return
err
;
}
return
0
;
}
static
int
lola_pcm_trigger
(
struct
snd_pcm_substream
*
substream
,
int
cmd
)
...
...
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