aboutsummaryrefslogtreecommitdiffstats
path: root/sound/drivers
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2009-09-04 02:45:11 -0400
committerTakashi Iwai <tiwai@suse.de>2009-09-04 02:45:11 -0400
commitb5d10781731ece07bb2049e7743907194a5cc3f1 (patch)
treeac13416d9e7ec24a155f4d71e3c9134204973eef /sound/drivers
parent30681bcf2b15a601b9460e6ddab22077998b8d4c (diff)
ALSA: dummy - Fix the timer calculation in systimer mode
Fix the expire-time calculation in the systimer mode when the buffer size isn't aligned to the period size. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/drivers')
-rw-r--r--sound/drivers/dummy.c29
1 files changed, 21 insertions, 8 deletions
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index 0a798bde0d03..e8e29bfb85ec 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -207,19 +207,18 @@ struct dummy_systimer_pcm {
207 struct timer_list timer; 207 struct timer_list timer;
208 unsigned long base_time; 208 unsigned long base_time;
209 unsigned int frac_pos; /* fractional sample position (based HZ) */ 209 unsigned int frac_pos; /* fractional sample position (based HZ) */
210 unsigned int frac_period_rest;
210 unsigned int frac_buffer_size; /* buffer_size * HZ */ 211 unsigned int frac_buffer_size; /* buffer_size * HZ */
211 unsigned int frac_period_size; /* period_size * HZ */ 212 unsigned int frac_period_size; /* period_size * HZ */
212 unsigned int rate; 213 unsigned int rate;
214 int elapsed;
213 struct snd_pcm_substream *substream; 215 struct snd_pcm_substream *substream;
214}; 216};
215 217
216static void dummy_systimer_rearm(struct dummy_systimer_pcm *dpcm) 218static void dummy_systimer_rearm(struct dummy_systimer_pcm *dpcm)
217{ 219{
218 unsigned long frac;
219
220 frac = dpcm->frac_pos % dpcm->frac_period_size;
221 dpcm->timer.expires = jiffies + 220 dpcm->timer.expires = jiffies +
222 (dpcm->frac_period_size + dpcm->rate - 1) / dpcm->rate; 221 (dpcm->frac_period_rest + dpcm->rate - 1) / dpcm->rate;
223 add_timer(&dpcm->timer); 222 add_timer(&dpcm->timer);
224} 223}
225 224
@@ -230,10 +229,16 @@ static void dummy_systimer_update(struct dummy_systimer_pcm *dpcm)
230 delta = jiffies - dpcm->base_time; 229 delta = jiffies - dpcm->base_time;
231 if (!delta) 230 if (!delta)
232 return; 231 return;
233 dpcm->base_time = jiffies; 232 dpcm->base_time += delta;
234 dpcm->frac_pos += delta * dpcm->rate; 233 delta *= dpcm->rate;
234 dpcm->frac_pos += delta;
235 while (dpcm->frac_pos >= dpcm->frac_buffer_size) 235 while (dpcm->frac_pos >= dpcm->frac_buffer_size)
236 dpcm->frac_pos -= dpcm->frac_buffer_size; 236 dpcm->frac_pos -= dpcm->frac_buffer_size;
237 while (dpcm->frac_period_rest <= delta) {
238 dpcm->elapsed++;
239 dpcm->frac_period_rest += dpcm->frac_period_size;
240 }
241 dpcm->frac_period_rest -= delta;
237} 242}
238 243
239static int dummy_systimer_start(struct snd_pcm_substream *substream) 244static int dummy_systimer_start(struct snd_pcm_substream *substream)
@@ -264,6 +269,8 @@ static int dummy_systimer_prepare(struct snd_pcm_substream *substream)
264 dpcm->rate = runtime->rate; 269 dpcm->rate = runtime->rate;
265 dpcm->frac_buffer_size = runtime->buffer_size * HZ; 270 dpcm->frac_buffer_size = runtime->buffer_size * HZ;
266 dpcm->frac_period_size = runtime->period_size * HZ; 271 dpcm->frac_period_size = runtime->period_size * HZ;
272 dpcm->frac_period_rest = dpcm->frac_period_size;
273 dpcm->elapsed = 0;
267 274
268 return 0; 275 return 0;
269} 276}
@@ -272,23 +279,29 @@ static void dummy_systimer_callback(unsigned long data)
272{ 279{
273 struct dummy_systimer_pcm *dpcm = (struct dummy_systimer_pcm *)data; 280 struct dummy_systimer_pcm *dpcm = (struct dummy_systimer_pcm *)data;
274 unsigned long flags; 281 unsigned long flags;
282 int elapsed = 0;
275 283
276 spin_lock_irqsave(&dpcm->lock, flags); 284 spin_lock_irqsave(&dpcm->lock, flags);
277 dummy_systimer_update(dpcm); 285 dummy_systimer_update(dpcm);
278 dummy_systimer_rearm(dpcm); 286 dummy_systimer_rearm(dpcm);
287 elapsed = dpcm->elapsed;
288 dpcm->elapsed = 0;
279 spin_unlock_irqrestore(&dpcm->lock, flags); 289 spin_unlock_irqrestore(&dpcm->lock, flags);
280 snd_pcm_period_elapsed(dpcm->substream); 290 if (elapsed)
291 snd_pcm_period_elapsed(dpcm->substream);
281} 292}
282 293
283static snd_pcm_uframes_t 294static snd_pcm_uframes_t
284dummy_systimer_pointer(struct snd_pcm_substream *substream) 295dummy_systimer_pointer(struct snd_pcm_substream *substream)
285{ 296{
286 struct dummy_systimer_pcm *dpcm = substream->runtime->private_data; 297 struct dummy_systimer_pcm *dpcm = substream->runtime->private_data;
298 snd_pcm_uframes_t pos;
287 299
288 spin_lock(&dpcm->lock); 300 spin_lock(&dpcm->lock);
289 dummy_systimer_update(dpcm); 301 dummy_systimer_update(dpcm);
302 pos = dpcm->frac_pos / HZ;
290 spin_unlock(&dpcm->lock); 303 spin_unlock(&dpcm->lock);
291 return dpcm->frac_pos / HZ; 304 return pos;
292} 305}
293 306
294static int dummy_systimer_create(struct snd_pcm_substream *substream) 307static int dummy_systimer_create(struct snd_pcm_substream *substream)