diff options
Diffstat (limited to 'sound/pci/lola/lola_pcm.c')
-rw-r--r-- | sound/pci/lola/lola_pcm.c | 49 |
1 files changed, 43 insertions, 6 deletions
diff --git a/sound/pci/lola/lola_pcm.c b/sound/pci/lola/lola_pcm.c index 4bb5b5bd6371..6be6b7e8f567 100644 --- a/sound/pci/lola/lola_pcm.c +++ b/sound/pci/lola/lola_pcm.c | |||
@@ -126,6 +126,22 @@ static void lola_stream_reset(struct lola *chip, struct lola_stream *str) | |||
126 | if (str->prepared) { | 126 | if (str->prepared) { |
127 | str->prepared = 0; | 127 | str->prepared = 0; |
128 | 128 | ||
129 | if (str->paused) { | ||
130 | /* finish pause - prepare for a new resume | ||
131 | * move this code later to trigger function, | ||
132 | * as this is also needed when resuming from pause | ||
133 | */ | ||
134 | str->paused = 0; | ||
135 | /* implement later loop for all streams */ | ||
136 | lola_stream_wait_for_fifo(chip, str, false); | ||
137 | lola_dsd_write(chip, str->dsd, CTL, LOLA_DSD_CTL_SRUN | | ||
138 | LOLA_DSD_CTL_IOCE | LOLA_DSD_CTL_DEIE); | ||
139 | /* end loop */ | ||
140 | /* implement later once more loop for all streams */ | ||
141 | lola_stream_wait_for_fifo(chip, str, true); | ||
142 | /* end loop */ | ||
143 | /* end finish pause */ | ||
144 | } | ||
129 | lola_dsd_write(chip, str->dsd, CTL, | 145 | lola_dsd_write(chip, str->dsd, CTL, |
130 | LOLA_DSD_CTL_IOCE | LOLA_DSD_CTL_DEIE); | 146 | LOLA_DSD_CTL_IOCE | LOLA_DSD_CTL_DEIE); |
131 | lola_stream_wait_for_fifo(chip, str, false); | 147 | lola_stream_wait_for_fifo(chip, str, false); |
@@ -178,12 +194,17 @@ static int lola_pcm_open(struct snd_pcm_substream *substream) | |||
178 | str->opened = 1; | 194 | str->opened = 1; |
179 | runtime->hw = lola_pcm_hw; | 195 | runtime->hw = lola_pcm_hw; |
180 | runtime->hw.channels_max = pcm->num_streams - str->index; | 196 | runtime->hw.channels_max = pcm->num_streams - str->index; |
181 | runtime->hw.rate_min = chip->sample_rate_min; | 197 | if (chip->sample_rate) { |
182 | runtime->hw.rate_max = chip->sample_rate_max; | 198 | /* sample rate is locked */ |
199 | runtime->hw.rate_min = chip->sample_rate; | ||
200 | runtime->hw.rate_max = chip->sample_rate; | ||
201 | } else { | ||
202 | runtime->hw.rate_min = chip->sample_rate_min; | ||
203 | runtime->hw.rate_max = chip->sample_rate_max; | ||
204 | } | ||
205 | chip->ref_count_rate++; | ||
183 | snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); | 206 | snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); |
184 | /* period size = multiple of chip->granularity (8, 16 or 32 frames) | 207 | /* period size = multiple of chip->granularity (8, 16 or 32 frames)*/ |
185 | * use LOLA_GRANULARITY_MAX = 32 for instance | ||
186 | */ | ||
187 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, | 208 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, |
188 | chip->granularity); | 209 | chip->granularity); |
189 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, | 210 | 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) | |||
215 | str->substream = NULL; | 236 | str->substream = NULL; |
216 | str->opened = 0; | 237 | str->opened = 0; |
217 | } | 238 | } |
239 | if (--chip->ref_count_rate == 0) { | ||
240 | /* release sample rate */ | ||
241 | chip->sample_rate = 0; | ||
242 | } | ||
218 | mutex_unlock(&chip->open_mutex); | 243 | mutex_unlock(&chip->open_mutex); |
219 | return 0; | 244 | return 0; |
220 | } | 245 | } |
@@ -427,6 +452,11 @@ static int lola_pcm_prepare(struct snd_pcm_substream *substream) | |||
427 | if (err < 0) | 452 | if (err < 0) |
428 | return err; | 453 | return err; |
429 | 454 | ||
455 | err = lola_set_sample_rate(chip, runtime->rate); | ||
456 | if (err < 0) | ||
457 | return err; | ||
458 | chip->sample_rate = runtime->rate; /* sample rate gets locked */ | ||
459 | |||
430 | err = lola_set_stream_config(chip, str, runtime->channels); | 460 | err = lola_set_stream_config(chip, str, runtime->channels); |
431 | if (err < 0) | 461 | if (err < 0) |
432 | return err; | 462 | return err; |
@@ -447,6 +477,7 @@ static int lola_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
447 | struct snd_pcm_substream *s; | 477 | struct snd_pcm_substream *s; |
448 | unsigned int start; | 478 | unsigned int start; |
449 | unsigned int tstamp; | 479 | unsigned int tstamp; |
480 | bool sync_streams; | ||
450 | 481 | ||
451 | switch (cmd) { | 482 | switch (cmd) { |
452 | case SNDRV_PCM_TRIGGER_START: | 483 | case SNDRV_PCM_TRIGGER_START: |
@@ -463,7 +494,12 @@ static int lola_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
463 | return -EINVAL; | 494 | return -EINVAL; |
464 | } | 495 | } |
465 | 496 | ||
466 | tstamp = lola_get_tstamp(chip, false); | 497 | /* |
498 | * sample correct synchronization is only needed starting several | ||
499 | * streams on stop or if only one stream do as quick as possible | ||
500 | */ | ||
501 | sync_streams = (start && snd_pcm_stream_linked(substream)); | ||
502 | tstamp = lola_get_tstamp(chip, !sync_streams); | ||
467 | spin_lock(&chip->reg_lock); | 503 | spin_lock(&chip->reg_lock); |
468 | snd_pcm_group_for_each_entry(s, substream) { | 504 | snd_pcm_group_for_each_entry(s, substream) { |
469 | if (s->pcm->card != substream->pcm->card) | 505 | if (s->pcm->card != substream->pcm->card) |
@@ -474,6 +510,7 @@ static int lola_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
474 | else | 510 | else |
475 | lola_stream_stop(chip, str, tstamp); | 511 | lola_stream_stop(chip, str, tstamp); |
476 | str->running = start; | 512 | str->running = start; |
513 | str->paused = !start; | ||
477 | snd_pcm_trigger_done(s, substream); | 514 | snd_pcm_trigger_done(s, substream); |
478 | } | 515 | } |
479 | spin_unlock(&chip->reg_lock); | 516 | spin_unlock(&chip->reg_lock); |