diff options
author | Takashi Iwai <tiwai@suse.de> | 2011-05-03 10:59:27 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-05-03 10:59:27 -0400 |
commit | 7e79f2267605e59492fef92b966dddc3c6a68b41 (patch) | |
tree | 65a091902884420f475ec284ef3b77a021ab647f /sound/pci/lola | |
parent | 8bd172dc96fba8ba5a7560afdc1ff7461c278e86 (diff) |
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>
Diffstat (limited to 'sound/pci/lola')
-rw-r--r-- | sound/pci/lola/lola.h | 4 | ||||
-rw-r--r-- | sound/pci/lola/lola_pcm.c | 49 |
2 files changed, 46 insertions, 7 deletions
diff --git a/sound/pci/lola/lola.h b/sound/pci/lola/lola.h index bc8110ff6b46..180c2c124620 100644 --- a/sound/pci/lola/lola.h +++ b/sound/pci/lola/lola.h | |||
@@ -306,6 +306,7 @@ struct lola_stream { | |||
306 | /* flags */ | 306 | /* flags */ |
307 | unsigned int opened:1; | 307 | unsigned int opened:1; |
308 | unsigned int prepared:1; | 308 | unsigned int prepared:1; |
309 | unsigned int paused:1; | ||
309 | unsigned int running:1; | 310 | unsigned int running:1; |
310 | }; | 311 | }; |
311 | 312 | ||
@@ -356,6 +357,8 @@ struct lola { | |||
356 | 357 | ||
357 | /* clock */ | 358 | /* clock */ |
358 | struct lola_clock_widget clock; | 359 | struct lola_clock_widget clock; |
360 | int ref_count_rate; | ||
361 | unsigned int sample_rate; | ||
359 | 362 | ||
360 | /* mixer */ | 363 | /* mixer */ |
361 | struct lola_mixer_widget mixer; | 364 | struct lola_mixer_widget mixer; |
@@ -370,7 +373,6 @@ struct lola { | |||
370 | unsigned int sample_rate_max; | 373 | unsigned int sample_rate_max; |
371 | 374 | ||
372 | /* flags */ | 375 | /* flags */ |
373 | unsigned int running :1; | ||
374 | unsigned int initialized :1; | 376 | unsigned int initialized :1; |
375 | unsigned int cold_reset :1; | 377 | unsigned int cold_reset :1; |
376 | 378 | ||
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); |