]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
ALSA: lola - Use a single BDL
authorTakashi Iwai <tiwai@suse.de>
Tue, 3 May 2011 14:41:02 +0000 (16:41 +0200)
committerTakashi Iwai <tiwai@suse.de>
Tue, 3 May 2011 14:41:02 +0000 (16:41 +0200)
Use a single BDL for both buffers instead of allocating for each.

Also a few tune-up to avoid the stream stalls in the PCM code and
the prelimianry work for SG-buffer support are added, too.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/pci/lola/lola.h
sound/pci/lola/lola_pcm.c

index 23831a1a95add410196145fd0fb5e09ecf0d467c..1041b0f0e20f8576dfe16199185c20600a56869f 100644 (file)
@@ -299,7 +299,6 @@ struct lola_stream {
        unsigned int bufsize;
        unsigned int period_bytes;
        unsigned int frags;
-       struct snd_dma_buffer bdl; /* BDL buffer */
 
        /* format + channel setup */
        unsigned int format_verb;
@@ -314,6 +313,7 @@ struct lola_stream {
 
 struct lola_pcm {
        unsigned int num_streams;
+       struct snd_dma_buffer bdl; /* BDL buffer */
        struct lola_stream streams[MAX_STREAM_COUNT];
 };
 
index bf17f921d45ff45b7975c9f809c5ced51381978f..a656439915c8dd29a2efeab532932a008243bdb0 100644 (file)
 #include <sound/pcm.h>
 #include "lola.h"
 
-#define BDL_SIZE               4096
-#define LOLA_MAX_BDL_ENTRIES   (BDL_SIZE / 16)
-#define LOLA_MAX_FRAG          32
+/* #define USE_SG_BUFFER */
+
+#define LOLA_MAX_BDL_ENTRIES   8
+#define LOLA_MAX_FRAG          8
 #define LOLA_MAX_BUF_SIZE      (1024*1024*1024)
+#define LOLA_BDL_ENTRY_SIZE    (16 * 16)
+
+#ifdef USE_SG_BUFFER
+#define get_addr(substream, ofs) \
+       snd_pcm_sgbuf_get_addr(substream, ofs)
+#define get_size(substream, ofs, size) \
+       snd_pcm_sgbuf_get_chunk_size(substream, ofs, size)
+#define ops_page       snd_pcm_sgbuf_ops_page
+#define PREALLOC_TYPE  SNDRV_DMA_TYPE_DEV_SG
+#else
+#define get_addr(substream, ofs) \
+       ((substream)->runtime->dma_addr + ofs)
+#define get_size(substream, ofs, size) \
+       (size)
+#define ops_page       NULL
+#define PREALLOC_TYPE  SNDRV_DMA_TYPE_DEV
+#endif
 
 static struct lola_pcm *lola_get_pcm(struct snd_pcm_substream *substream)
 {
@@ -101,7 +119,7 @@ static void lola_stream_clear(struct lola *chip, struct lola_stream *str)
 
 static void wait_for_srst_clear(struct lola *chip, struct lola_stream *str)
 {
-       unsigned long end_time = jiffies + msecs_to_jiffies(50);
+       unsigned long end_time = jiffies + msecs_to_jiffies(200);
        while (time_before(jiffies, end_time)) {
                unsigned int val;
                val = lola_dsd_read(chip, str->dsd, CTL);
@@ -115,16 +133,16 @@ static void wait_for_srst_clear(struct lola *chip, struct lola_stream *str)
 static void lola_stream_reset(struct lola *chip, struct lola_stream *str)
 {
        lola_dsd_write(chip, str->dsd, CTL, LOLA_DSD_CTL_SRST);
+       wait_for_srst_clear(chip, str);
        lola_dsd_write(chip, str->dsd, LVI, 0);
        lola_dsd_write(chip, str->dsd, BDPU, 0);
        lola_dsd_write(chip, str->dsd, BDPL, 0);
-       wait_for_srst_clear(chip, str);
 }
 
 static int lola_stream_wait_for_fifo_ready(struct lola *chip,
                                           struct lola_stream *str)
 {
-       unsigned long end_time = jiffies + msecs_to_jiffies(50);
+       unsigned long end_time = jiffies + msecs_to_jiffies(1000);
        while (time_before(jiffies, end_time)) {
                unsigned int val = lola_dsd_read(chip, str->dsd, STS);
                if (val & LOLA_DSD_STS_FIFORDY)
@@ -164,21 +182,12 @@ static int lola_pcm_open(struct snd_pcm_substream *substream)
        struct lola_pcm *pcm = lola_get_pcm(substream);
        struct lola_stream *str = lola_get_stream(substream);
        struct snd_pcm_runtime *runtime = substream->runtime;
-       int err;
 
        mutex_lock(&chip->open_mutex);
        if (str->opened) {
                mutex_unlock(&chip->open_mutex);
                return -EBUSY;
        }
-       err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
-                                 snd_dma_pci_data(chip->pci),
-                                 PAGE_SIZE, &str->bdl);
-       if (err < 0) {
-               mutex_unlock(&chip->open_mutex);
-               printk(KERN_ERR SFX "Can't allocate BDL\n");
-               return err;
-       }
        str->substream = substream;
        str->master = NULL;
        str->opened = 1;
@@ -216,7 +225,6 @@ static int lola_pcm_close(struct snd_pcm_substream *substream)
                str->substream = NULL;
                str->opened = 0;
        }
-       snd_dma_free_pages(&str->bdl);
        mutex_unlock(&chip->open_mutex);
        return 0;
 }
@@ -262,12 +270,12 @@ static int setup_bdle(struct snd_pcm_substream *substream,
                if (str->frags >= LOLA_MAX_BDL_ENTRIES)
                        return -EINVAL;
 
-               addr = snd_pcm_sgbuf_get_addr(substream, ofs);
+               addr = get_addr(substream, ofs);
                /* program the address field of the BDL entry */
                bdl[0] = cpu_to_le32((u32)addr);
                bdl[1] = cpu_to_le32(upper_32_bits(addr));
                /* program the size field of the BDL entry */
-               chunk = snd_pcm_sgbuf_get_chunk_size(substream, ofs, size);
+               chunk = get_size(substream, ofs, size);
                bdl[2] = cpu_to_le32(chunk);
                /* program the IOC to enable interrupt
                 * only when the whole fragment is processed
@@ -285,7 +293,7 @@ static int setup_bdle(struct snd_pcm_substream *substream,
 /*
  * set up BDL entries
  */
-static int lola_setup_periods(struct lola *chip,
+static int lola_setup_periods(struct lola *chip, struct lola_pcm *pcm,
                              struct snd_pcm_substream *substream,
                              struct lola_stream *str)
 {
@@ -296,7 +304,7 @@ static int lola_setup_periods(struct lola *chip,
        periods = str->bufsize / period_bytes;
 
        /* program the initial BDL entries */
-       bdl = (u32 *)str->bdl.area;
+       bdl = (u32 *)(pcm->bdl.area + LOLA_BDL_ENTRY_SIZE * str->index);
        ofs = 0;
        str->frags = 0;
        for (i = 0; i < periods; i++) {
@@ -371,13 +379,14 @@ static int lola_set_stream_config(struct lola *chip,
 /*
  * set up the SD for streaming
  */
-static int lola_setup_controller(struct lola *chip, struct lola_stream *str)
+static int lola_setup_controller(struct lola *chip, struct lola_pcm *pcm,
+                                struct lola_stream *str)
 {
-       /* make sure the run bit is zero for SD */
-       lola_stream_clear(chip, str);
+       dma_addr_t bdl;
        /* set up BDL */
-       lola_dsd_write(chip, str->dsd, BDPL, (u32)str->bdl.addr);
-       lola_dsd_write(chip, str->dsd, BDPU, upper_32_bits(str->bdl.addr));
+       bdl = pcm->bdl.addr + LOLA_BDL_ENTRY_SIZE * str->index;
+       lola_dsd_write(chip, str->dsd, BDPL, (u32)bdl);
+       lola_dsd_write(chip, str->dsd, BDPU, upper_32_bits(bdl));
        /* program the stream LVI (last valid index) of the BDL */
        lola_dsd_write(chip, str->dsd, LVI, str->frags - 1);
        lola_stream_stop(chip, str, lola_get_tstamp(chip, false));
@@ -418,7 +427,7 @@ static int lola_pcm_prepare(struct snd_pcm_substream *substream)
                str->bufsize = bufsize;
                str->period_bytes = period_bytes;
                str->format_verb = format_verb;
-               err = lola_setup_periods(chip, substream, str);
+               err = lola_setup_periods(chip, pcm, substream, str);
                if (err < 0)
                        return err;
        }
@@ -427,7 +436,7 @@ static int lola_pcm_prepare(struct snd_pcm_substream *substream)
        if (err < 0)
                return err;
 
-       return lola_setup_controller(chip, str);
+       return lola_setup_controller(chip, pcm, str);
 }
 
 static int lola_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
@@ -504,7 +513,7 @@ static struct snd_pcm_ops lola_pcm_ops = {
        .prepare = lola_pcm_prepare,
        .trigger = lola_pcm_trigger,
        .pointer = lola_pcm_pointer,
-       .page = snd_pcm_sgbuf_ops_page,
+       .page = ops_page,
 };
 
 int __devinit lola_create_pcm(struct lola *chip)
@@ -512,6 +521,14 @@ int __devinit lola_create_pcm(struct lola *chip)
        struct snd_pcm *pcm;
        int i, err;
 
+       for (i = 0; i < 2; i++) {
+               err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
+                                         snd_dma_pci_data(chip->pci),
+                                         PAGE_SIZE, &chip->pcm[i].bdl);
+               if (err < 0)
+                       return err;
+       }
+
        err = snd_pcm_new(chip->card, "Digigram Lola", 0,
                          chip->pcm[SNDRV_PCM_STREAM_PLAYBACK].num_streams,
                          chip->pcm[SNDRV_PCM_STREAM_CAPTURE].num_streams,
@@ -525,7 +542,7 @@ int __devinit lola_create_pcm(struct lola *chip)
                        snd_pcm_set_ops(pcm, i, &lola_pcm_ops);
        }
        /* buffer pre-allocation */
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
+       snd_pcm_lib_preallocate_pages_for_all(pcm, PREALLOC_TYPE,
                                              snd_dma_pci_data(chip->pci),
                                              1024 * 64, 32 * 1024 * 1024);
        return 0;
@@ -533,7 +550,8 @@ int __devinit lola_create_pcm(struct lola *chip)
 
 void lola_free_pcm(struct lola *chip)
 {
-       /* nothing to do */
+       snd_dma_free_pages(&chip->pcm[0].bdl);
+       snd_dma_free_pages(&chip->pcm[1].bdl);
 }
 
 /*