aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/lola
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2011-05-03 10:41:02 -0400
committerTakashi Iwai <tiwai@suse.de>2011-05-03 10:41:02 -0400
commit333ff3971f374d9a057fd6d1492a2ef78989974d (patch)
tree194f15d828c478ff3dfe22e597cf202383fd2ddd /sound/pci/lola
parenta426c787233c87587b6cac797ac840162bdb09c2 (diff)
ALSA: lola - Use a single BDL
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>
Diffstat (limited to 'sound/pci/lola')
-rw-r--r--sound/pci/lola/lola.h2
-rw-r--r--sound/pci/lola/lola_pcm.c78
2 files changed, 49 insertions, 31 deletions
diff --git a/sound/pci/lola/lola.h b/sound/pci/lola/lola.h
index 23831a1a95ad..1041b0f0e20f 100644
--- a/sound/pci/lola/lola.h
+++ b/sound/pci/lola/lola.h
@@ -299,7 +299,6 @@ struct lola_stream {
299 unsigned int bufsize; 299 unsigned int bufsize;
300 unsigned int period_bytes; 300 unsigned int period_bytes;
301 unsigned int frags; 301 unsigned int frags;
302 struct snd_dma_buffer bdl; /* BDL buffer */
303 302
304 /* format + channel setup */ 303 /* format + channel setup */
305 unsigned int format_verb; 304 unsigned int format_verb;
@@ -314,6 +313,7 @@ struct lola_stream {
314 313
315struct lola_pcm { 314struct lola_pcm {
316 unsigned int num_streams; 315 unsigned int num_streams;
316 struct snd_dma_buffer bdl; /* BDL buffer */
317 struct lola_stream streams[MAX_STREAM_COUNT]; 317 struct lola_stream streams[MAX_STREAM_COUNT];
318}; 318};
319 319
diff --git a/sound/pci/lola/lola_pcm.c b/sound/pci/lola/lola_pcm.c
index bf17f921d45f..a656439915c8 100644
--- a/sound/pci/lola/lola_pcm.c
+++ b/sound/pci/lola/lola_pcm.c
@@ -26,10 +26,28 @@
26#include <sound/pcm.h> 26#include <sound/pcm.h>
27#include "lola.h" 27#include "lola.h"
28 28
29#define BDL_SIZE 4096 29/* #define USE_SG_BUFFER */
30#define LOLA_MAX_BDL_ENTRIES (BDL_SIZE / 16) 30
31#define LOLA_MAX_FRAG 32 31#define LOLA_MAX_BDL_ENTRIES 8
32#define LOLA_MAX_FRAG 8
32#define LOLA_MAX_BUF_SIZE (1024*1024*1024) 33#define LOLA_MAX_BUF_SIZE (1024*1024*1024)
34#define LOLA_BDL_ENTRY_SIZE (16 * 16)
35
36#ifdef USE_SG_BUFFER
37#define get_addr(substream, ofs) \
38 snd_pcm_sgbuf_get_addr(substream, ofs)
39#define get_size(substream, ofs, size) \
40 snd_pcm_sgbuf_get_chunk_size(substream, ofs, size)
41#define ops_page snd_pcm_sgbuf_ops_page
42#define PREALLOC_TYPE SNDRV_DMA_TYPE_DEV_SG
43#else
44#define get_addr(substream, ofs) \
45 ((substream)->runtime->dma_addr + ofs)
46#define get_size(substream, ofs, size) \
47 (size)
48#define ops_page NULL
49#define PREALLOC_TYPE SNDRV_DMA_TYPE_DEV
50#endif
33 51
34static struct lola_pcm *lola_get_pcm(struct snd_pcm_substream *substream) 52static struct lola_pcm *lola_get_pcm(struct snd_pcm_substream *substream)
35{ 53{
@@ -101,7 +119,7 @@ static void lola_stream_clear(struct lola *chip, struct lola_stream *str)
101 119
102static void wait_for_srst_clear(struct lola *chip, struct lola_stream *str) 120static void wait_for_srst_clear(struct lola *chip, struct lola_stream *str)
103{ 121{
104 unsigned long end_time = jiffies + msecs_to_jiffies(50); 122 unsigned long end_time = jiffies + msecs_to_jiffies(200);
105 while (time_before(jiffies, end_time)) { 123 while (time_before(jiffies, end_time)) {
106 unsigned int val; 124 unsigned int val;
107 val = lola_dsd_read(chip, str->dsd, CTL); 125 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)
115static void lola_stream_reset(struct lola *chip, struct lola_stream *str) 133static void lola_stream_reset(struct lola *chip, struct lola_stream *str)
116{ 134{
117 lola_dsd_write(chip, str->dsd, CTL, LOLA_DSD_CTL_SRST); 135 lola_dsd_write(chip, str->dsd, CTL, LOLA_DSD_CTL_SRST);
136 wait_for_srst_clear(chip, str);
118 lola_dsd_write(chip, str->dsd, LVI, 0); 137 lola_dsd_write(chip, str->dsd, LVI, 0);
119 lola_dsd_write(chip, str->dsd, BDPU, 0); 138 lola_dsd_write(chip, str->dsd, BDPU, 0);
120 lola_dsd_write(chip, str->dsd, BDPL, 0); 139 lola_dsd_write(chip, str->dsd, BDPL, 0);
121 wait_for_srst_clear(chip, str);
122} 140}
123 141
124static int lola_stream_wait_for_fifo_ready(struct lola *chip, 142static int lola_stream_wait_for_fifo_ready(struct lola *chip,
125 struct lola_stream *str) 143 struct lola_stream *str)
126{ 144{
127 unsigned long end_time = jiffies + msecs_to_jiffies(50); 145 unsigned long end_time = jiffies + msecs_to_jiffies(1000);
128 while (time_before(jiffies, end_time)) { 146 while (time_before(jiffies, end_time)) {
129 unsigned int val = lola_dsd_read(chip, str->dsd, STS); 147 unsigned int val = lola_dsd_read(chip, str->dsd, STS);
130 if (val & LOLA_DSD_STS_FIFORDY) 148 if (val & LOLA_DSD_STS_FIFORDY)
@@ -164,21 +182,12 @@ static int lola_pcm_open(struct snd_pcm_substream *substream)
164 struct lola_pcm *pcm = lola_get_pcm(substream); 182 struct lola_pcm *pcm = lola_get_pcm(substream);
165 struct lola_stream *str = lola_get_stream(substream); 183 struct lola_stream *str = lola_get_stream(substream);
166 struct snd_pcm_runtime *runtime = substream->runtime; 184 struct snd_pcm_runtime *runtime = substream->runtime;
167 int err;
168 185
169 mutex_lock(&chip->open_mutex); 186 mutex_lock(&chip->open_mutex);
170 if (str->opened) { 187 if (str->opened) {
171 mutex_unlock(&chip->open_mutex); 188 mutex_unlock(&chip->open_mutex);
172 return -EBUSY; 189 return -EBUSY;
173 } 190 }
174 err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
175 snd_dma_pci_data(chip->pci),
176 PAGE_SIZE, &str->bdl);
177 if (err < 0) {
178 mutex_unlock(&chip->open_mutex);
179 printk(KERN_ERR SFX "Can't allocate BDL\n");
180 return err;
181 }
182 str->substream = substream; 191 str->substream = substream;
183 str->master = NULL; 192 str->master = NULL;
184 str->opened = 1; 193 str->opened = 1;
@@ -216,7 +225,6 @@ static int lola_pcm_close(struct snd_pcm_substream *substream)
216 str->substream = NULL; 225 str->substream = NULL;
217 str->opened = 0; 226 str->opened = 0;
218 } 227 }
219 snd_dma_free_pages(&str->bdl);
220 mutex_unlock(&chip->open_mutex); 228 mutex_unlock(&chip->open_mutex);
221 return 0; 229 return 0;
222} 230}
@@ -262,12 +270,12 @@ static int setup_bdle(struct snd_pcm_substream *substream,
262 if (str->frags >= LOLA_MAX_BDL_ENTRIES) 270 if (str->frags >= LOLA_MAX_BDL_ENTRIES)
263 return -EINVAL; 271 return -EINVAL;
264 272
265 addr = snd_pcm_sgbuf_get_addr(substream, ofs); 273 addr = get_addr(substream, ofs);
266 /* program the address field of the BDL entry */ 274 /* program the address field of the BDL entry */
267 bdl[0] = cpu_to_le32((u32)addr); 275 bdl[0] = cpu_to_le32((u32)addr);
268 bdl[1] = cpu_to_le32(upper_32_bits(addr)); 276 bdl[1] = cpu_to_le32(upper_32_bits(addr));
269 /* program the size field of the BDL entry */ 277 /* program the size field of the BDL entry */
270 chunk = snd_pcm_sgbuf_get_chunk_size(substream, ofs, size); 278 chunk = get_size(substream, ofs, size);
271 bdl[2] = cpu_to_le32(chunk); 279 bdl[2] = cpu_to_le32(chunk);
272 /* program the IOC to enable interrupt 280 /* program the IOC to enable interrupt
273 * only when the whole fragment is processed 281 * only when the whole fragment is processed
@@ -285,7 +293,7 @@ static int setup_bdle(struct snd_pcm_substream *substream,
285/* 293/*
286 * set up BDL entries 294 * set up BDL entries
287 */ 295 */
288static int lola_setup_periods(struct lola *chip, 296static int lola_setup_periods(struct lola *chip, struct lola_pcm *pcm,
289 struct snd_pcm_substream *substream, 297 struct snd_pcm_substream *substream,
290 struct lola_stream *str) 298 struct lola_stream *str)
291{ 299{
@@ -296,7 +304,7 @@ static int lola_setup_periods(struct lola *chip,
296 periods = str->bufsize / period_bytes; 304 periods = str->bufsize / period_bytes;
297 305
298 /* program the initial BDL entries */ 306 /* program the initial BDL entries */
299 bdl = (u32 *)str->bdl.area; 307 bdl = (u32 *)(pcm->bdl.area + LOLA_BDL_ENTRY_SIZE * str->index);
300 ofs = 0; 308 ofs = 0;
301 str->frags = 0; 309 str->frags = 0;
302 for (i = 0; i < periods; i++) { 310 for (i = 0; i < periods; i++) {
@@ -371,13 +379,14 @@ static int lola_set_stream_config(struct lola *chip,
371/* 379/*
372 * set up the SD for streaming 380 * set up the SD for streaming
373 */ 381 */
374static int lola_setup_controller(struct lola *chip, struct lola_stream *str) 382static int lola_setup_controller(struct lola *chip, struct lola_pcm *pcm,
383 struct lola_stream *str)
375{ 384{
376 /* make sure the run bit is zero for SD */ 385 dma_addr_t bdl;
377 lola_stream_clear(chip, str);
378 /* set up BDL */ 386 /* set up BDL */
379 lola_dsd_write(chip, str->dsd, BDPL, (u32)str->bdl.addr); 387 bdl = pcm->bdl.addr + LOLA_BDL_ENTRY_SIZE * str->index;
380 lola_dsd_write(chip, str->dsd, BDPU, upper_32_bits(str->bdl.addr)); 388 lola_dsd_write(chip, str->dsd, BDPL, (u32)bdl);
389 lola_dsd_write(chip, str->dsd, BDPU, upper_32_bits(bdl));
381 /* program the stream LVI (last valid index) of the BDL */ 390 /* program the stream LVI (last valid index) of the BDL */
382 lola_dsd_write(chip, str->dsd, LVI, str->frags - 1); 391 lola_dsd_write(chip, str->dsd, LVI, str->frags - 1);
383 lola_stream_stop(chip, str, lola_get_tstamp(chip, false)); 392 lola_stream_stop(chip, str, lola_get_tstamp(chip, false));
@@ -418,7 +427,7 @@ static int lola_pcm_prepare(struct snd_pcm_substream *substream)
418 str->bufsize = bufsize; 427 str->bufsize = bufsize;
419 str->period_bytes = period_bytes; 428 str->period_bytes = period_bytes;
420 str->format_verb = format_verb; 429 str->format_verb = format_verb;
421 err = lola_setup_periods(chip, substream, str); 430 err = lola_setup_periods(chip, pcm, substream, str);
422 if (err < 0) 431 if (err < 0)
423 return err; 432 return err;
424 } 433 }
@@ -427,7 +436,7 @@ static int lola_pcm_prepare(struct snd_pcm_substream *substream)
427 if (err < 0) 436 if (err < 0)
428 return err; 437 return err;
429 438
430 return lola_setup_controller(chip, str); 439 return lola_setup_controller(chip, pcm, str);
431} 440}
432 441
433static int lola_pcm_trigger(struct snd_pcm_substream *substream, int cmd) 442static int lola_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
@@ -504,7 +513,7 @@ static struct snd_pcm_ops lola_pcm_ops = {
504 .prepare = lola_pcm_prepare, 513 .prepare = lola_pcm_prepare,
505 .trigger = lola_pcm_trigger, 514 .trigger = lola_pcm_trigger,
506 .pointer = lola_pcm_pointer, 515 .pointer = lola_pcm_pointer,
507 .page = snd_pcm_sgbuf_ops_page, 516 .page = ops_page,
508}; 517};
509 518
510int __devinit lola_create_pcm(struct lola *chip) 519int __devinit lola_create_pcm(struct lola *chip)
@@ -512,6 +521,14 @@ int __devinit lola_create_pcm(struct lola *chip)
512 struct snd_pcm *pcm; 521 struct snd_pcm *pcm;
513 int i, err; 522 int i, err;
514 523
524 for (i = 0; i < 2; i++) {
525 err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
526 snd_dma_pci_data(chip->pci),
527 PAGE_SIZE, &chip->pcm[i].bdl);
528 if (err < 0)
529 return err;
530 }
531
515 err = snd_pcm_new(chip->card, "Digigram Lola", 0, 532 err = snd_pcm_new(chip->card, "Digigram Lola", 0,
516 chip->pcm[SNDRV_PCM_STREAM_PLAYBACK].num_streams, 533 chip->pcm[SNDRV_PCM_STREAM_PLAYBACK].num_streams,
517 chip->pcm[SNDRV_PCM_STREAM_CAPTURE].num_streams, 534 chip->pcm[SNDRV_PCM_STREAM_CAPTURE].num_streams,
@@ -525,7 +542,7 @@ int __devinit lola_create_pcm(struct lola *chip)
525 snd_pcm_set_ops(pcm, i, &lola_pcm_ops); 542 snd_pcm_set_ops(pcm, i, &lola_pcm_ops);
526 } 543 }
527 /* buffer pre-allocation */ 544 /* buffer pre-allocation */
528 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, 545 snd_pcm_lib_preallocate_pages_for_all(pcm, PREALLOC_TYPE,
529 snd_dma_pci_data(chip->pci), 546 snd_dma_pci_data(chip->pci),
530 1024 * 64, 32 * 1024 * 1024); 547 1024 * 64, 32 * 1024 * 1024);
531 return 0; 548 return 0;
@@ -533,7 +550,8 @@ int __devinit lola_create_pcm(struct lola *chip)
533 550
534void lola_free_pcm(struct lola *chip) 551void lola_free_pcm(struct lola *chip)
535{ 552{
536 /* nothing to do */ 553 snd_dma_free_pages(&chip->pcm[0].bdl);
554 snd_dma_free_pages(&chip->pcm[1].bdl);
537} 555}
538 556
539/* 557/*