forked from Minki/linux
ALSA: lola - Add SRC refcounting
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>
This commit is contained in:
parent
8bd172dc96
commit
7e79f22676
@ -306,6 +306,7 @@ struct lola_stream {
|
||||
/* flags */
|
||||
unsigned int opened:1;
|
||||
unsigned int prepared:1;
|
||||
unsigned int paused:1;
|
||||
unsigned int running:1;
|
||||
};
|
||||
|
||||
@ -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;
|
||||
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
@ -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,
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
@ -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:
|
||||
@ -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)
|
||||
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user