aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/lola
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2011-05-03 10:59:27 -0400
committerTakashi Iwai <tiwai@suse.de>2011-05-03 10:59:27 -0400
commit7e79f2267605e59492fef92b966dddc3c6a68b41 (patch)
tree65a091902884420f475ec284ef3b77a021ab647f /sound/pci/lola
parent8bd172dc96fba8ba5a7560afdc1ff7461c278e86 (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.h4
-rw-r--r--sound/pci/lola/lola_pcm.c49
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);