aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/lola
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2011-05-03 10:47:03 -0400
committerTakashi Iwai <tiwai@suse.de>2011-05-03 10:47:03 -0400
commit0f8f56c959c9c4a65a5ad13f1b49d97db30b5c2f (patch)
tree87fde35926c524d466fa0c4897d05e68e3c26718 /sound/pci/lola
parent333ff3971f374d9a057fd6d1492a2ef78989974d (diff)
ALSA: lola - Fix PCM stalls
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/lola')
-rw-r--r--sound/pci/lola/lola.c17
-rw-r--r--sound/pci/lola/lola.h1
-rw-r--r--sound/pci/lola/lola_pcm.c103
3 files changed, 74 insertions, 47 deletions
diff --git a/sound/pci/lola/lola.c b/sound/pci/lola/lola.c
index 16c6cad2e7cd..4d8221505b9e 100644
--- a/sound/pci/lola/lola.c
+++ b/sound/pci/lola/lola.c
@@ -73,6 +73,7 @@ static int corb_send_verb(struct lola *chip, unsigned int nid,
73 chip->last_data = data; 73 chip->last_data = data;
74 chip->last_extdata = extdata; 74 chip->last_extdata = extdata;
75 data |= (nid << 20) | (verb << 8); 75 data |= (nid << 20) | (verb << 8);
76
76 spin_lock_irqsave(&chip->reg_lock, flags); 77 spin_lock_irqsave(&chip->reg_lock, flags);
77 if (chip->rirb.cmds < LOLA_CORB_ENTRIES - 1) { 78 if (chip->rirb.cmds < LOLA_CORB_ENTRIES - 1) {
78 unsigned int wp = chip->corb.wp + 1; 79 unsigned int wp = chip->corb.wp + 1;
@@ -338,8 +339,6 @@ static int setup_corb_rirb(struct lola *chip)
338 chip->corb.buf = (u32 *)chip->rb.area; 339 chip->corb.buf = (u32 *)chip->rb.area;
339 chip->rirb.addr = chip->rb.addr + 2048; 340 chip->rirb.addr = chip->rb.addr + 2048;
340 chip->rirb.buf = (u32 *)(chip->rb.area + 2048); 341 chip->rirb.buf = (u32 *)(chip->rb.area + 2048);
341 lola_writel(chip, BAR0, CORBLBASE, (u32)chip->corb.addr);
342 lola_writel(chip, BAR0, CORBUBASE, upper_32_bits(chip->corb.addr));
343 342
344 /* disable ringbuffer DMAs */ 343 /* disable ringbuffer DMAs */
345 lola_writeb(chip, BAR0, RIRBCTL, 0); 344 lola_writeb(chip, BAR0, RIRBCTL, 0);
@@ -496,6 +495,10 @@ static int lola_parse_tree(struct lola *chip)
496 if (!chip->cold_reset) { 495 if (!chip->cold_reset) {
497 lola_reset_setups(chip); 496 lola_reset_setups(chip);
498 chip->cold_reset = 1; 497 chip->cold_reset = 1;
498 } else {
499 /* set the granularity if it is not the default */
500 if (chip->granularity != LOLA_GRANULARITY_MIN)
501 lola_set_granularity(chip, chip->granularity, true);
499 } 502 }
500 503
501 return 0; 504 return 0;
@@ -561,8 +564,14 @@ static int __devinit lola_create(struct snd_card *card, struct pci_dev *pci,
561 chip->pci = pci; 564 chip->pci = pci;
562 chip->irq = -1; 565 chip->irq = -1;
563 566
564 chip->sample_rate_min = 48000; 567 /* below a sample_rate of 16kHz the analogue audio quality
565 chip->granularity = LOLA_GRANULARITY_MIN; 568 * is NOT excellent
569 */
570 chip->sample_rate_min = 16000;
571 /* for instance use always max granularity which is compatible
572 * with all sample rates
573 */
574 chip->granularity = LOLA_GRANULARITY_MAX;
566 575
567 err = pci_request_regions(pci, DRVNAME); 576 err = pci_request_regions(pci, DRVNAME);
568 if (err < 0) { 577 if (err < 0) {
diff --git a/sound/pci/lola/lola.h b/sound/pci/lola/lola.h
index 1041b0f0e20f..839779dc32f9 100644
--- a/sound/pci/lola/lola.h
+++ b/sound/pci/lola/lola.h
@@ -305,6 +305,7 @@ struct lola_stream {
305 305
306 /* flags */ 306 /* flags */
307 unsigned int opened:1; 307 unsigned int opened:1;
308 unsigned int prepared:1;
308 unsigned int running:1; 309 unsigned int running:1;
309}; 310};
310 311
diff --git a/sound/pci/lola/lola_pcm.c b/sound/pci/lola/lola_pcm.c
index a656439915c8..ef738e6c9919 100644
--- a/sound/pci/lola/lola_pcm.c
+++ b/sound/pci/lola/lola_pcm.c
@@ -29,7 +29,6 @@
29/* #define USE_SG_BUFFER */ 29/* #define USE_SG_BUFFER */
30 30
31#define LOLA_MAX_BDL_ENTRIES 8 31#define LOLA_MAX_BDL_ENTRIES 8
32#define LOLA_MAX_FRAG 8
33#define LOLA_MAX_BUF_SIZE (1024*1024*1024) 32#define LOLA_MAX_BUF_SIZE (1024*1024*1024)
34#define LOLA_BDL_ENTRY_SIZE (16 * 16) 33#define LOLA_BDL_ENTRY_SIZE (16 * 16)
35 34
@@ -111,12 +110,6 @@ static void lola_stream_stop(struct lola *chip, struct lola_stream *str,
111 lola_stream_clear_pending_irq(chip, str); 110 lola_stream_clear_pending_irq(chip, str);
112} 111}
113 112
114static void lola_stream_clear(struct lola *chip, struct lola_stream *str)
115{
116 lola_dsd_write(chip, str->dsd, CTL, 0);
117 lola_stream_clear_pending_irq(chip, str);
118}
119
120static void wait_for_srst_clear(struct lola *chip, struct lola_stream *str) 113static void wait_for_srst_clear(struct lola *chip, struct lola_stream *str)
121{ 114{
122 unsigned long end_time = jiffies + msecs_to_jiffies(200); 115 unsigned long end_time = jiffies + msecs_to_jiffies(200);
@@ -130,22 +123,15 @@ static void wait_for_srst_clear(struct lola *chip, struct lola_stream *str)
130 printk(KERN_WARNING SFX "SRST not clear (stream %d)\n", str->dsd); 123 printk(KERN_WARNING SFX "SRST not clear (stream %d)\n", str->dsd);
131} 124}
132 125
133static void lola_stream_reset(struct lola *chip, struct lola_stream *str) 126static int lola_stream_wait_for_fifo(struct lola *chip,
127 struct lola_stream *str,
128 bool ready)
134{ 129{
135 lola_dsd_write(chip, str->dsd, CTL, LOLA_DSD_CTL_SRST); 130 unsigned int val = ready ? LOLA_DSD_STS_FIFORDY : 0;
136 wait_for_srst_clear(chip, str); 131 unsigned long end_time = jiffies + msecs_to_jiffies(200);
137 lola_dsd_write(chip, str->dsd, LVI, 0);
138 lola_dsd_write(chip, str->dsd, BDPU, 0);
139 lola_dsd_write(chip, str->dsd, BDPL, 0);
140}
141
142static int lola_stream_wait_for_fifo_ready(struct lola *chip,
143 struct lola_stream *str)
144{
145 unsigned long end_time = jiffies + msecs_to_jiffies(1000);
146 while (time_before(jiffies, end_time)) { 132 while (time_before(jiffies, end_time)) {
147 unsigned int val = lola_dsd_read(chip, str->dsd, STS); 133 unsigned int reg = lola_dsd_read(chip, str->dsd, STS);
148 if (val & LOLA_DSD_STS_FIFORDY) 134 if ((reg & LOLA_DSD_STS_FIFORDY) == val)
149 return 0; 135 return 0;
150 msleep(1); 136 msleep(1);
151 } 137 }
@@ -153,6 +139,23 @@ static int lola_stream_wait_for_fifo_ready(struct lola *chip,
153 return -EIO; 139 return -EIO;
154} 140}
155 141
142static void lola_stream_reset(struct lola *chip, struct lola_stream *str)
143{
144 if (str->prepared) {
145 str->prepared = 0;
146
147 lola_dsd_write(chip, str->dsd, CTL,
148 LOLA_DSD_CTL_IOCE | LOLA_DSD_CTL_DEIE);
149 lola_stream_wait_for_fifo(chip, str, false);
150 lola_stream_clear_pending_irq(chip, str);
151 lola_dsd_write(chip, str->dsd, CTL, LOLA_DSD_CTL_SRST);
152 lola_dsd_write(chip, str->dsd, LVI, 0);
153 lola_dsd_write(chip, str->dsd, BDPU, 0);
154 lola_dsd_write(chip, str->dsd, BDPL, 0);
155 wait_for_srst_clear(chip, str);
156 }
157}
158
156static struct snd_pcm_hardware lola_pcm_hw = { 159static struct snd_pcm_hardware lola_pcm_hw = {
157 .info = (SNDRV_PCM_INFO_MMAP | 160 .info = (SNDRV_PCM_INFO_MMAP |
158 SNDRV_PCM_INFO_INTERLEAVED | 161 SNDRV_PCM_INFO_INTERLEAVED |
@@ -163,16 +166,16 @@ static struct snd_pcm_hardware lola_pcm_hw = {
163 SNDRV_PCM_FMTBIT_S24_LE | 166 SNDRV_PCM_FMTBIT_S24_LE |
164 SNDRV_PCM_FMTBIT_S32_LE | 167 SNDRV_PCM_FMTBIT_S32_LE |
165 SNDRV_PCM_FMTBIT_FLOAT_LE), 168 SNDRV_PCM_FMTBIT_FLOAT_LE),
166 .rates = SNDRV_PCM_RATE_48000, 169 .rates = SNDRV_PCM_RATE_8000_192000,
167 .rate_min = 48000, 170 .rate_min = 8000,
168 .rate_max = 48000, 171 .rate_max = 192000,
169 .channels_min = 1, 172 .channels_min = 1,
170 .channels_max = 2, 173 .channels_max = 2,
171 .buffer_bytes_max = LOLA_MAX_BUF_SIZE, 174 .buffer_bytes_max = LOLA_MAX_BUF_SIZE,
172 .period_bytes_min = 128, 175 .period_bytes_min = 128,
173 .period_bytes_max = LOLA_MAX_BUF_SIZE / 2, 176 .period_bytes_max = LOLA_MAX_BUF_SIZE / 2,
174 .periods_min = 2, 177 .periods_min = 2,
175 .periods_max = LOLA_MAX_FRAG, 178 .periods_max = LOLA_MAX_BDL_ENTRIES,
176 .fifo_size = 0, 179 .fifo_size = 0,
177}; 180};
178 181
@@ -194,10 +197,13 @@ static int lola_pcm_open(struct snd_pcm_substream *substream)
194 runtime->hw = lola_pcm_hw; 197 runtime->hw = lola_pcm_hw;
195 runtime->hw.channels_max = pcm->num_streams - str->index; 198 runtime->hw.channels_max = pcm->num_streams - str->index;
196 snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); 199 snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
197 snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 200 /* period size = multiple of chip->granularity (8, 16 or 32 frames)
198 128); 201 * use LOLA_GRANULARITY_MAX = 32 for instance
199 snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 202 */
200 128); 203 snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
204 LOLA_GRANULARITY_MAX);
205 snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
206 LOLA_GRANULARITY_MAX);
201 mutex_unlock(&chip->open_mutex); 207 mutex_unlock(&chip->open_mutex);
202 return 0; 208 return 0;
203} 209}
@@ -383,16 +389,24 @@ static int lola_setup_controller(struct lola *chip, struct lola_pcm *pcm,
383 struct lola_stream *str) 389 struct lola_stream *str)
384{ 390{
385 dma_addr_t bdl; 391 dma_addr_t bdl;
392
393 if (str->prepared)
394 return -EINVAL;
395
386 /* set up BDL */ 396 /* set up BDL */
387 bdl = pcm->bdl.addr + LOLA_BDL_ENTRY_SIZE * str->index; 397 bdl = pcm->bdl.addr + LOLA_BDL_ENTRY_SIZE * str->index;
388 lola_dsd_write(chip, str->dsd, BDPL, (u32)bdl); 398 lola_dsd_write(chip, str->dsd, BDPL, (u32)bdl);
389 lola_dsd_write(chip, str->dsd, BDPU, upper_32_bits(bdl)); 399 lola_dsd_write(chip, str->dsd, BDPU, upper_32_bits(bdl));
390 /* program the stream LVI (last valid index) of the BDL */ 400 /* program the stream LVI (last valid index) of the BDL */
391 lola_dsd_write(chip, str->dsd, LVI, str->frags - 1); 401 lola_dsd_write(chip, str->dsd, LVI, str->frags - 1);
392 lola_stream_stop(chip, str, lola_get_tstamp(chip, false)); 402 lola_stream_clear_pending_irq(chip, str);
393 lola_stream_wait_for_fifo_ready(chip, str);
394 403
395 return 0; 404 lola_dsd_write(chip, str->dsd, CTL,
405 LOLA_DSD_CTL_IOCE | LOLA_DSD_CTL_DEIE | LOLA_DSD_CTL_SRUN);
406
407 str->prepared = 1;
408
409 return lola_stream_wait_for_fifo(chip, str, true);
396} 410}
397 411
398static int lola_pcm_prepare(struct snd_pcm_substream *substream) 412static int lola_pcm_prepare(struct snd_pcm_substream *substream)
@@ -421,22 +435,25 @@ static int lola_pcm_prepare(struct snd_pcm_substream *substream)
421 period_bytes = snd_pcm_lib_period_bytes(substream); 435 period_bytes = snd_pcm_lib_period_bytes(substream);
422 format_verb = lola_get_format_verb(substream); 436 format_verb = lola_get_format_verb(substream);
423 437
424 if (bufsize != str->bufsize || 438 str->bufsize = bufsize;
425 period_bytes != str->period_bytes || 439 str->period_bytes = period_bytes;
426 format_verb != str->format_verb) { 440 str->format_verb = format_verb;
427 str->bufsize = bufsize; 441
428 str->period_bytes = period_bytes; 442 err = lola_setup_periods(chip, pcm, substream, str);
429 str->format_verb = format_verb; 443 if (err < 0)
430 err = lola_setup_periods(chip, pcm, substream, str); 444 return err;
431 if (err < 0)
432 return err;
433 }
434 445
435 err = lola_set_stream_config(chip, str, runtime->channels); 446 err = lola_set_stream_config(chip, str, runtime->channels);
436 if (err < 0) 447 if (err < 0)
437 return err; 448 return err;
438 449
439 return lola_setup_controller(chip, pcm, str); 450 err = lola_setup_controller(chip, pcm, str);
451 if (err < 0) {
452 lola_stream_reset(chip, str);
453 return err;
454 }
455
456 return 0;
440} 457}
441 458
442static int lola_pcm_trigger(struct snd_pcm_substream *substream, int cmd) 459static int lola_pcm_trigger(struct snd_pcm_substream *substream, int cmd)