Skip to content

Commit

Permalink
ALSA: lola - Add SRC refcounting
Browse files Browse the repository at this point in the history
Added the refcounting for the exclusive SRC control.
Also, fixed the possible stall after PCM pause operations.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
  • Loading branch information
Takashi Iwai committed May 3, 2011
1 parent 8bd172d commit 7e79f22
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 7 deletions.
4 changes: 3 additions & 1 deletion sound/pci/lola/lola.h
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@ struct lola_stream {
/* flags */
unsigned int opened:1;
unsigned int prepared:1;
unsigned int paused:1;
unsigned int running:1;
};

Expand Down Expand Up @@ -356,6 +357,8 @@ struct lola {

/* clock */
struct lola_clock_widget clock;
int ref_count_rate;
unsigned int sample_rate;

/* mixer */
struct lola_mixer_widget mixer;
Expand All @@ -370,7 +373,6 @@ struct lola {
unsigned int sample_rate_max;

/* flags */
unsigned int running :1;
unsigned int initialized :1;
unsigned int cold_reset :1;

Expand Down
49 changes: 43 additions & 6 deletions sound/pci/lola/lola_pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,22 @@ static void lola_stream_reset(struct lola *chip, struct lola_stream *str)
if (str->prepared) {
str->prepared = 0;

if (str->paused) {
/* finish pause - prepare for a new resume
* move this code later to trigger function,
* as this is also needed when resuming from pause
*/
str->paused = 0;
/* implement later loop for all streams */
lola_stream_wait_for_fifo(chip, str, false);
lola_dsd_write(chip, str->dsd, CTL, LOLA_DSD_CTL_SRUN |
LOLA_DSD_CTL_IOCE | LOLA_DSD_CTL_DEIE);
/* end loop */
/* implement later once more loop for all streams */
lola_stream_wait_for_fifo(chip, str, true);
/* end loop */
/* end finish pause */
}
lola_dsd_write(chip, str->dsd, CTL,
LOLA_DSD_CTL_IOCE | LOLA_DSD_CTL_DEIE);
lola_stream_wait_for_fifo(chip, str, false);
Expand Down Expand Up @@ -178,12 +194,17 @@ static int lola_pcm_open(struct snd_pcm_substream *substream)
str->opened = 1;
runtime->hw = lola_pcm_hw;
runtime->hw.channels_max = pcm->num_streams - str->index;
runtime->hw.rate_min = chip->sample_rate_min;
runtime->hw.rate_max = chip->sample_rate_max;
if (chip->sample_rate) {
/* sample rate is locked */
runtime->hw.rate_min = chip->sample_rate;
runtime->hw.rate_max = chip->sample_rate;
} else {
runtime->hw.rate_min = chip->sample_rate_min;
runtime->hw.rate_max = chip->sample_rate_max;
}
chip->ref_count_rate++;
snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
/* period size = multiple of chip->granularity (8, 16 or 32 frames)
* use LOLA_GRANULARITY_MAX = 32 for instance
*/
/* period size = multiple of chip->granularity (8, 16 or 32 frames)*/
snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
chip->granularity);
snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
Expand Down Expand Up @@ -215,6 +236,10 @@ static int lola_pcm_close(struct snd_pcm_substream *substream)
str->substream = NULL;
str->opened = 0;
}
if (--chip->ref_count_rate == 0) {
/* release sample rate */
chip->sample_rate = 0;
}
mutex_unlock(&chip->open_mutex);
return 0;
}
Expand Down Expand Up @@ -427,6 +452,11 @@ static int lola_pcm_prepare(struct snd_pcm_substream *substream)
if (err < 0)
return err;

err = lola_set_sample_rate(chip, runtime->rate);
if (err < 0)
return err;
chip->sample_rate = runtime->rate; /* sample rate gets locked */

err = lola_set_stream_config(chip, str, runtime->channels);
if (err < 0)
return err;
Expand All @@ -447,6 +477,7 @@ static int lola_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
struct snd_pcm_substream *s;
unsigned int start;
unsigned int tstamp;
bool sync_streams;

switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
Expand All @@ -463,7 +494,12 @@ static int lola_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
return -EINVAL;
}

tstamp = lola_get_tstamp(chip, false);
/*
* sample correct synchronization is only needed starting several
* streams on stop or if only one stream do as quick as possible
*/
sync_streams = (start && snd_pcm_stream_linked(substream));
tstamp = lola_get_tstamp(chip, !sync_streams);
spin_lock(&chip->reg_lock);
snd_pcm_group_for_each_entry(s, substream) {
if (s->pcm->card != substream->pcm->card)
Expand All @@ -474,6 +510,7 @@ static int lola_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
else
lola_stream_stop(chip, str, tstamp);
str->running = start;
str->paused = !start;
snd_pcm_trigger_done(s, substream);
}
spin_unlock(&chip->reg_lock);
Expand Down

0 comments on commit 7e79f22

Please sign in to comment.