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>
This commit is contained in:
Takashi Iwai 2009-07-16 18:19:12 +02:00
Родитель 9fe856e47e
Коммит add7c0a6a4
1 изменённых файлов: 16 добавлений и 18 удалений

Просмотреть файл

@ -1002,29 +1002,27 @@ snd_ca0106_pcm_pointer_playback(struct snd_pcm_substream *substream)
struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_ca0106_pcm *epcm = runtime->private_data;
snd_pcm_uframes_t ptr, ptr1, ptr2,ptr3,ptr4 = 0;
unsigned int ptr, prev_ptr;
int channel = epcm->channel_id;
int timeout = 10;
if (!epcm->running)
return 0;
ptr3 = snd_ca0106_ptr_read(emu, PLAYBACK_LIST_PTR, channel);
ptr1 = snd_ca0106_ptr_read(emu, PLAYBACK_POINTER, channel);
ptr4 = snd_ca0106_ptr_read(emu, PLAYBACK_LIST_PTR, channel);
if (ptr3 != ptr4) ptr1 = snd_ca0106_ptr_read(emu, PLAYBACK_POINTER, channel);
ptr2 = bytes_to_frames(runtime, ptr1);
ptr2+= (ptr4 >> 3) * runtime->period_size;
ptr=ptr2;
if (ptr >= runtime->buffer_size)
ptr -= runtime->buffer_size;
/*
printk(KERN_DEBUG "ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, "
"buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n",
ptr1, ptr2, ptr, (int)runtime->buffer_size,
(int)runtime->period_size, (int)runtime->frame_bits,
(int)runtime->rate);
*/
return ptr;
prev_ptr = -1;
do {
ptr = snd_ca0106_ptr_read(emu, PLAYBACK_LIST_PTR, channel);
ptr = (ptr >> 3) * runtime->period_size;
ptr += bytes_to_frames(runtime,
snd_ca0106_ptr_read(emu, PLAYBACK_POINTER, channel));
if (ptr >= runtime->buffer_size)
ptr -= runtime->buffer_size;
if (prev_ptr == ptr)
return ptr;
prev_ptr = ptr;
} while (--timeout);
snd_printk(KERN_WARNING "ca0106: unstable DMA pointer!\n");
return 0;
}
/* pointer_capture callback */