aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2009-07-16 12:19:12 -0400
committerTakashi Iwai <tiwai@suse.de>2010-09-07 05:54:16 -0400
commitadd7c0a6a4b8669ebd726f9c08ba6002900ca671 (patch)
tree81c28ffce3985feafc2a6d07f33a7052c763c425
parent9fe856e47e1751204faf3d604c6d20ab24bd3b93 (diff)
ALSA: ca0106 - clean up playback pointer callback
Clean up the playback pointer callback function a bit, and make the pointer check more strictly to avoid bogus pointers. Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/pci/ca0106/ca0106_main.c34
1 files changed, 16 insertions, 18 deletions
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index 0a3d3d6e77b4..8e69620da20b 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -1002,29 +1002,27 @@ snd_ca0106_pcm_pointer_playback(struct snd_pcm_substream *substream)
1002 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream); 1002 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
1003 struct snd_pcm_runtime *runtime = substream->runtime; 1003 struct snd_pcm_runtime *runtime = substream->runtime;
1004 struct snd_ca0106_pcm *epcm = runtime->private_data; 1004 struct snd_ca0106_pcm *epcm = runtime->private_data;
1005 snd_pcm_uframes_t ptr, ptr1, ptr2,ptr3,ptr4 = 0; 1005 unsigned int ptr, prev_ptr;
1006 int channel = epcm->channel_id; 1006 int channel = epcm->channel_id;
1007 int timeout = 10;
1007 1008
1008 if (!epcm->running) 1009 if (!epcm->running)
1009 return 0; 1010 return 0;
1010 1011
1011 ptr3 = snd_ca0106_ptr_read(emu, PLAYBACK_LIST_PTR, channel); 1012 prev_ptr = -1;
1012 ptr1 = snd_ca0106_ptr_read(emu, PLAYBACK_POINTER, channel); 1013 do {
1013 ptr4 = snd_ca0106_ptr_read(emu, PLAYBACK_LIST_PTR, channel); 1014 ptr = snd_ca0106_ptr_read(emu, PLAYBACK_LIST_PTR, channel);
1014 if (ptr3 != ptr4) ptr1 = snd_ca0106_ptr_read(emu, PLAYBACK_POINTER, channel); 1015 ptr = (ptr >> 3) * runtime->period_size;
1015 ptr2 = bytes_to_frames(runtime, ptr1); 1016 ptr += bytes_to_frames(runtime,
1016 ptr2+= (ptr4 >> 3) * runtime->period_size; 1017 snd_ca0106_ptr_read(emu, PLAYBACK_POINTER, channel));
1017 ptr=ptr2; 1018 if (ptr >= runtime->buffer_size)
1018 if (ptr >= runtime->buffer_size) 1019 ptr -= runtime->buffer_size;
1019 ptr -= runtime->buffer_size; 1020 if (prev_ptr == ptr)
1020 /* 1021 return ptr;
1021 printk(KERN_DEBUG "ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, " 1022 prev_ptr = ptr;
1022 "buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n", 1023 } while (--timeout);
1023 ptr1, ptr2, ptr, (int)runtime->buffer_size, 1024 snd_printk(KERN_WARNING "ca0106: unstable DMA pointer!\n");
1024 (int)runtime->period_size, (int)runtime->frame_bits, 1025 return 0;
1025 (int)runtime->rate);
1026 */
1027 return ptr;
1028} 1026}
1029 1027
1030/* pointer_capture callback */ 1028/* pointer_capture callback */