aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/lola
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2011-05-03 11:02:35 -0400
committerTakashi Iwai <tiwai@suse.de>2011-05-03 11:02:35 -0400
commitc7aad3c317afc05418414c95e877173799145d0b (patch)
treed091d02fdbd48f6b38207149aa7c07719d7d2b9c /sound/pci/lola
parent7e79f2267605e59492fef92b966dddc3c6a68b41 (diff)
ALSA: lola - Add sync in loop implementation
For assuring the synchronized state with the pause operation, loop over the all linked streams and waits until all get ready in a loop. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/lola')
-rw-r--r--sound/pci/lola/lola_pcm.c76
1 files changed, 59 insertions, 17 deletions
diff --git a/sound/pci/lola/lola_pcm.c b/sound/pci/lola/lola_pcm.c
index 6be6b7e8f567..5c0014cbff07 100644
--- a/sound/pci/lola/lola_pcm.c
+++ b/sound/pci/lola/lola_pcm.c
@@ -121,27 +121,69 @@ static int lola_stream_wait_for_fifo(struct lola *chip,
121 return -EIO; 121 return -EIO;
122} 122}
123 123
124static void lola_stream_reset(struct lola *chip, struct lola_stream *str) 124/* sync for FIFO ready/empty for all linked streams;
125 * clear paused flag when FIFO gets ready again
126 */
127static int lola_sync_wait_for_fifo(struct lola *chip,
128 struct snd_pcm_substream *substream,
129 bool ready)
125{ 130{
126 if (str->prepared) { 131 unsigned int val = ready ? LOLA_DSD_STS_FIFORDY : 0;
127 str->prepared = 0; 132 unsigned long end_time = jiffies + msecs_to_jiffies(200);
133 struct snd_pcm_substream *s;
134 int pending = 0;
135
136 while (time_before(jiffies, end_time)) {
137 pending = 0;
138 snd_pcm_group_for_each_entry(s, substream) {
139 struct lola_stream *str;
140 if (s->pcm->card != substream->pcm->card)
141 continue;
142 str = lola_get_stream(s);
143 if (str->prepared && str->paused) {
144 unsigned int reg;
145 reg = lola_dsd_read(chip, str->dsd, STS);
146 if ((reg & LOLA_DSD_STS_FIFORDY) != val) {
147 pending = str->dsd + 1;
148 break;
149 }
150 if (ready)
151 str->paused = 0;
152 }
153 }
154 if (!pending)
155 return 0;
156 msleep(1);
157 }
158 printk(KERN_WARNING SFX "FIFO not ready (pending %d)\n", pending - 1);
159 return -EIO;
160}
128 161
129 if (str->paused) { 162/* finish pause - prepare for a new resume */
130 /* finish pause - prepare for a new resume 163static void lola_sync_pause(struct lola *chip,
131 * move this code later to trigger function, 164 struct snd_pcm_substream *substream)
132 * as this is also needed when resuming from pause 165{
133 */ 166 struct snd_pcm_substream *s;
134 str->paused = 0; 167
135 /* implement later loop for all streams */ 168 lola_sync_wait_for_fifo(chip, substream, false);
136 lola_stream_wait_for_fifo(chip, str, false); 169 snd_pcm_group_for_each_entry(s, substream) {
170 struct lola_stream *str;
171 if (s->pcm->card != substream->pcm->card)
172 continue;
173 str = lola_get_stream(s);
174 if (str->paused && str->prepared)
137 lola_dsd_write(chip, str->dsd, CTL, LOLA_DSD_CTL_SRUN | 175 lola_dsd_write(chip, str->dsd, CTL, LOLA_DSD_CTL_SRUN |
138 LOLA_DSD_CTL_IOCE | LOLA_DSD_CTL_DEIE); 176 LOLA_DSD_CTL_IOCE | LOLA_DSD_CTL_DEIE);
139 /* end loop */ 177 }
140 /* implement later once more loop for all streams */ 178 lola_sync_wait_for_fifo(chip, substream, true);
141 lola_stream_wait_for_fifo(chip, str, true); 179}
142 /* end loop */ 180
143 /* end finish pause */ 181static void lola_stream_reset(struct lola *chip, struct lola_stream *str)
144 } 182{
183 if (str->prepared) {
184 if (str->paused)
185 lola_sync_pause(chip, str->substream);
186 str->prepared = 0;
145 lola_dsd_write(chip, str->dsd, CTL, 187 lola_dsd_write(chip, str->dsd, CTL,
146 LOLA_DSD_CTL_IOCE | LOLA_DSD_CTL_DEIE); 188 LOLA_DSD_CTL_IOCE | LOLA_DSD_CTL_DEIE);
147 lola_stream_wait_for_fifo(chip, str, false); 189 lola_stream_wait_for_fifo(chip, str, false);