ALSA: asihpi: Handle playback drained status better
authorEliot Blennerhassett <eblennerhassett@audioscience.com>
Tue, 5 Apr 2011 08:55:43 +0000 (20:55 +1200)
committerTakashi Iwai <tiwai@suse.de>
Tue, 5 Apr 2011 09:47:08 +0000 (11:47 +0200)
Use the card drained status reporting for playback,
but allow it to persist for a few timer cycles before
signalling XRUN, to allow card to recover by itself.

Signed-off-by: Eliot Blennerhassett <eblennerhassett@audioscience.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/pci/asihpi/asihpi.c

index 434342f874ff63534963935a629351281e02df6e..a5226e3af3d7964f12dbdc360c7f45b61168ae83 100644 (file)
@@ -165,6 +165,7 @@ struct snd_card_asihpi_pcm {
        unsigned int pcm_buf_host_rw_ofs; /* Host R/W pos */
        unsigned int pcm_buf_dma_ofs;   /* DMA R/W offset in buffer */
        unsigned int pcm_buf_elapsed_dma_ofs;   /* DMA R/W offset in buffer */
+       unsigned int drained_count;
        struct snd_pcm_substream *substream;
        u32 h_stream;
        struct hpi_format format;
@@ -592,6 +593,7 @@ static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream,
                        if (substream->stream != s->stream)
                                continue;
 
+                       ds->drained_count = 0;
                        if ((s->stream == SNDRV_PCM_STREAM_PLAYBACK) &&
                                (card->support_mmap)) {
                                /* How do I know how much valid data is present
@@ -771,12 +773,18 @@ static void snd_card_asihpi_timer_function(unsigned long data)
                                    (on_card_bytes < ds->pcm_buf_host_rw_ofs)) {
                                        hpi_handle_error(hpi_stream_start(ds->h_stream));
                                        snd_printdd("P%d start\n", s->number);
+                                       ds->drained_count = 0;
                                }
                        } else if (state == HPI_STATE_DRAINED) {
                                snd_printd(KERN_WARNING "P%d drained\n",
                                                s->number);
-                               /*snd_pcm_stop(s, SNDRV_PCM_STATE_XRUN);
-                               continue; */
+                               ds->drained_count++;
+                               if (ds->drained_count > 2) {
+                                       snd_pcm_stop(s, SNDRV_PCM_STATE_XRUN);
+                                       continue;
+                               }
+                       } else {
+                               ds->drained_count = 0;
                        }
                } else
                        pcm_buf_dma_ofs = bytes_avail + ds->pcm_buf_host_rw_ofs;