Loading sound/pci/lola/lola.c +13 −4 Original line number Diff line number Diff line Loading @@ -73,6 +73,7 @@ static int corb_send_verb(struct lola *chip, unsigned int nid, chip->last_data = data; chip->last_extdata = extdata; data |= (nid << 20) | (verb << 8); spin_lock_irqsave(&chip->reg_lock, flags); if (chip->rirb.cmds < LOLA_CORB_ENTRIES - 1) { unsigned int wp = chip->corb.wp + 1; Loading Loading @@ -338,8 +339,6 @@ static int setup_corb_rirb(struct lola *chip) chip->corb.buf = (u32 *)chip->rb.area; chip->rirb.addr = chip->rb.addr + 2048; chip->rirb.buf = (u32 *)(chip->rb.area + 2048); lola_writel(chip, BAR0, CORBLBASE, (u32)chip->corb.addr); lola_writel(chip, BAR0, CORBUBASE, upper_32_bits(chip->corb.addr)); /* disable ringbuffer DMAs */ lola_writeb(chip, BAR0, RIRBCTL, 0); Loading Loading @@ -496,6 +495,10 @@ static int lola_parse_tree(struct lola *chip) if (!chip->cold_reset) { lola_reset_setups(chip); chip->cold_reset = 1; } else { /* set the granularity if it is not the default */ if (chip->granularity != LOLA_GRANULARITY_MIN) lola_set_granularity(chip, chip->granularity, true); } return 0; Loading Loading @@ -561,8 +564,14 @@ static int __devinit lola_create(struct snd_card *card, struct pci_dev *pci, chip->pci = pci; chip->irq = -1; chip->sample_rate_min = 48000; chip->granularity = LOLA_GRANULARITY_MIN; /* below a sample_rate of 16kHz the analogue audio quality * is NOT excellent */ chip->sample_rate_min = 16000; /* for instance use always max granularity which is compatible * with all sample rates */ chip->granularity = LOLA_GRANULARITY_MAX; err = pci_request_regions(pci, DRVNAME); if (err < 0) { Loading sound/pci/lola/lola.h +1 −0 Original line number Diff line number Diff line Loading @@ -305,6 +305,7 @@ struct lola_stream { /* flags */ unsigned int opened:1; unsigned int prepared:1; unsigned int running:1; }; Loading sound/pci/lola/lola_pcm.c +60 −43 Original line number Diff line number Diff line Loading @@ -29,7 +29,6 @@ /* #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) Loading Loading @@ -111,12 +110,6 @@ static void lola_stream_stop(struct lola *chip, struct lola_stream *str, lola_stream_clear_pending_irq(chip, str); } static void lola_stream_clear(struct lola *chip, struct lola_stream *str) { lola_dsd_write(chip, str->dsd, CTL, 0); lola_stream_clear_pending_irq(chip, str); } static void wait_for_srst_clear(struct lola *chip, struct lola_stream *str) { unsigned long end_time = jiffies + msecs_to_jiffies(200); Loading @@ -130,22 +123,15 @@ static void wait_for_srst_clear(struct lola *chip, struct lola_stream *str) printk(KERN_WARNING SFX "SRST not clear (stream %d)\n", str->dsd); } 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); } static int lola_stream_wait_for_fifo_ready(struct lola *chip, struct lola_stream *str) static int lola_stream_wait_for_fifo(struct lola *chip, struct lola_stream *str, bool ready) { unsigned long end_time = jiffies + msecs_to_jiffies(1000); unsigned int val = ready ? LOLA_DSD_STS_FIFORDY : 0; unsigned long end_time = jiffies + msecs_to_jiffies(200); while (time_before(jiffies, end_time)) { unsigned int val = lola_dsd_read(chip, str->dsd, STS); if (val & LOLA_DSD_STS_FIFORDY) unsigned int reg = lola_dsd_read(chip, str->dsd, STS); if ((reg & LOLA_DSD_STS_FIFORDY) == val) return 0; msleep(1); } Loading @@ -153,6 +139,23 @@ static int lola_stream_wait_for_fifo_ready(struct lola *chip, return -EIO; } static void lola_stream_reset(struct lola *chip, struct lola_stream *str) { if (str->prepared) { str->prepared = 0; lola_dsd_write(chip, str->dsd, CTL, LOLA_DSD_CTL_IOCE | LOLA_DSD_CTL_DEIE); lola_stream_wait_for_fifo(chip, str, false); lola_stream_clear_pending_irq(chip, str); lola_dsd_write(chip, str->dsd, CTL, LOLA_DSD_CTL_SRST); 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 struct snd_pcm_hardware lola_pcm_hw = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | Loading @@ -163,16 +166,16 @@ static struct snd_pcm_hardware lola_pcm_hw = { SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_FLOAT_LE), .rates = SNDRV_PCM_RATE_48000, .rate_min = 48000, .rate_max = 48000, .rates = SNDRV_PCM_RATE_8000_192000, .rate_min = 8000, .rate_max = 192000, .channels_min = 1, .channels_max = 2, .buffer_bytes_max = LOLA_MAX_BUF_SIZE, .period_bytes_min = 128, .period_bytes_max = LOLA_MAX_BUF_SIZE / 2, .periods_min = 2, .periods_max = LOLA_MAX_FRAG, .periods_max = LOLA_MAX_BDL_ENTRIES, .fifo_size = 0, }; Loading @@ -194,10 +197,13 @@ static int lola_pcm_open(struct snd_pcm_substream *substream) runtime->hw = lola_pcm_hw; runtime->hw.channels_max = pcm->num_streams - str->index; snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 128); snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 128); /* period size = multiple of chip->granularity (8, 16 or 32 frames) * use LOLA_GRANULARITY_MAX = 32 for instance */ snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, LOLA_GRANULARITY_MAX); snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, LOLA_GRANULARITY_MAX); mutex_unlock(&chip->open_mutex); return 0; } Loading Loading @@ -383,16 +389,24 @@ static int lola_setup_controller(struct lola *chip, struct lola_pcm *pcm, struct lola_stream *str) { dma_addr_t bdl; if (str->prepared) return -EINVAL; /* set up BDL */ 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)); lola_stream_wait_for_fifo_ready(chip, str); lola_stream_clear_pending_irq(chip, str); return 0; lola_dsd_write(chip, str->dsd, CTL, LOLA_DSD_CTL_IOCE | LOLA_DSD_CTL_DEIE | LOLA_DSD_CTL_SRUN); str->prepared = 1; return lola_stream_wait_for_fifo(chip, str, true); } static int lola_pcm_prepare(struct snd_pcm_substream *substream) Loading Loading @@ -421,22 +435,25 @@ static int lola_pcm_prepare(struct snd_pcm_substream *substream) period_bytes = snd_pcm_lib_period_bytes(substream); format_verb = lola_get_format_verb(substream); if (bufsize != str->bufsize || period_bytes != str->period_bytes || format_verb != str->format_verb) { str->bufsize = bufsize; str->period_bytes = period_bytes; str->format_verb = format_verb; err = lola_setup_periods(chip, pcm, substream, str); if (err < 0) return err; } err = lola_set_stream_config(chip, str, runtime->channels); if (err < 0) return err; return lola_setup_controller(chip, pcm, str); err = lola_setup_controller(chip, pcm, str); if (err < 0) { lola_stream_reset(chip, str); return err; } return 0; } static int lola_pcm_trigger(struct snd_pcm_substream *substream, int cmd) Loading Loading
sound/pci/lola/lola.c +13 −4 Original line number Diff line number Diff line Loading @@ -73,6 +73,7 @@ static int corb_send_verb(struct lola *chip, unsigned int nid, chip->last_data = data; chip->last_extdata = extdata; data |= (nid << 20) | (verb << 8); spin_lock_irqsave(&chip->reg_lock, flags); if (chip->rirb.cmds < LOLA_CORB_ENTRIES - 1) { unsigned int wp = chip->corb.wp + 1; Loading Loading @@ -338,8 +339,6 @@ static int setup_corb_rirb(struct lola *chip) chip->corb.buf = (u32 *)chip->rb.area; chip->rirb.addr = chip->rb.addr + 2048; chip->rirb.buf = (u32 *)(chip->rb.area + 2048); lola_writel(chip, BAR0, CORBLBASE, (u32)chip->corb.addr); lola_writel(chip, BAR0, CORBUBASE, upper_32_bits(chip->corb.addr)); /* disable ringbuffer DMAs */ lola_writeb(chip, BAR0, RIRBCTL, 0); Loading Loading @@ -496,6 +495,10 @@ static int lola_parse_tree(struct lola *chip) if (!chip->cold_reset) { lola_reset_setups(chip); chip->cold_reset = 1; } else { /* set the granularity if it is not the default */ if (chip->granularity != LOLA_GRANULARITY_MIN) lola_set_granularity(chip, chip->granularity, true); } return 0; Loading Loading @@ -561,8 +564,14 @@ static int __devinit lola_create(struct snd_card *card, struct pci_dev *pci, chip->pci = pci; chip->irq = -1; chip->sample_rate_min = 48000; chip->granularity = LOLA_GRANULARITY_MIN; /* below a sample_rate of 16kHz the analogue audio quality * is NOT excellent */ chip->sample_rate_min = 16000; /* for instance use always max granularity which is compatible * with all sample rates */ chip->granularity = LOLA_GRANULARITY_MAX; err = pci_request_regions(pci, DRVNAME); if (err < 0) { Loading
sound/pci/lola/lola.h +1 −0 Original line number Diff line number Diff line Loading @@ -305,6 +305,7 @@ struct lola_stream { /* flags */ unsigned int opened:1; unsigned int prepared:1; unsigned int running:1; }; Loading
sound/pci/lola/lola_pcm.c +60 −43 Original line number Diff line number Diff line Loading @@ -29,7 +29,6 @@ /* #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) Loading Loading @@ -111,12 +110,6 @@ static void lola_stream_stop(struct lola *chip, struct lola_stream *str, lola_stream_clear_pending_irq(chip, str); } static void lola_stream_clear(struct lola *chip, struct lola_stream *str) { lola_dsd_write(chip, str->dsd, CTL, 0); lola_stream_clear_pending_irq(chip, str); } static void wait_for_srst_clear(struct lola *chip, struct lola_stream *str) { unsigned long end_time = jiffies + msecs_to_jiffies(200); Loading @@ -130,22 +123,15 @@ static void wait_for_srst_clear(struct lola *chip, struct lola_stream *str) printk(KERN_WARNING SFX "SRST not clear (stream %d)\n", str->dsd); } 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); } static int lola_stream_wait_for_fifo_ready(struct lola *chip, struct lola_stream *str) static int lola_stream_wait_for_fifo(struct lola *chip, struct lola_stream *str, bool ready) { unsigned long end_time = jiffies + msecs_to_jiffies(1000); unsigned int val = ready ? LOLA_DSD_STS_FIFORDY : 0; unsigned long end_time = jiffies + msecs_to_jiffies(200); while (time_before(jiffies, end_time)) { unsigned int val = lola_dsd_read(chip, str->dsd, STS); if (val & LOLA_DSD_STS_FIFORDY) unsigned int reg = lola_dsd_read(chip, str->dsd, STS); if ((reg & LOLA_DSD_STS_FIFORDY) == val) return 0; msleep(1); } Loading @@ -153,6 +139,23 @@ static int lola_stream_wait_for_fifo_ready(struct lola *chip, return -EIO; } static void lola_stream_reset(struct lola *chip, struct lola_stream *str) { if (str->prepared) { str->prepared = 0; lola_dsd_write(chip, str->dsd, CTL, LOLA_DSD_CTL_IOCE | LOLA_DSD_CTL_DEIE); lola_stream_wait_for_fifo(chip, str, false); lola_stream_clear_pending_irq(chip, str); lola_dsd_write(chip, str->dsd, CTL, LOLA_DSD_CTL_SRST); 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 struct snd_pcm_hardware lola_pcm_hw = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | Loading @@ -163,16 +166,16 @@ static struct snd_pcm_hardware lola_pcm_hw = { SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_FLOAT_LE), .rates = SNDRV_PCM_RATE_48000, .rate_min = 48000, .rate_max = 48000, .rates = SNDRV_PCM_RATE_8000_192000, .rate_min = 8000, .rate_max = 192000, .channels_min = 1, .channels_max = 2, .buffer_bytes_max = LOLA_MAX_BUF_SIZE, .period_bytes_min = 128, .period_bytes_max = LOLA_MAX_BUF_SIZE / 2, .periods_min = 2, .periods_max = LOLA_MAX_FRAG, .periods_max = LOLA_MAX_BDL_ENTRIES, .fifo_size = 0, }; Loading @@ -194,10 +197,13 @@ static int lola_pcm_open(struct snd_pcm_substream *substream) runtime->hw = lola_pcm_hw; runtime->hw.channels_max = pcm->num_streams - str->index; snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 128); snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 128); /* period size = multiple of chip->granularity (8, 16 or 32 frames) * use LOLA_GRANULARITY_MAX = 32 for instance */ snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, LOLA_GRANULARITY_MAX); snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, LOLA_GRANULARITY_MAX); mutex_unlock(&chip->open_mutex); return 0; } Loading Loading @@ -383,16 +389,24 @@ static int lola_setup_controller(struct lola *chip, struct lola_pcm *pcm, struct lola_stream *str) { dma_addr_t bdl; if (str->prepared) return -EINVAL; /* set up BDL */ 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)); lola_stream_wait_for_fifo_ready(chip, str); lola_stream_clear_pending_irq(chip, str); return 0; lola_dsd_write(chip, str->dsd, CTL, LOLA_DSD_CTL_IOCE | LOLA_DSD_CTL_DEIE | LOLA_DSD_CTL_SRUN); str->prepared = 1; return lola_stream_wait_for_fifo(chip, str, true); } static int lola_pcm_prepare(struct snd_pcm_substream *substream) Loading Loading @@ -421,22 +435,25 @@ static int lola_pcm_prepare(struct snd_pcm_substream *substream) period_bytes = snd_pcm_lib_period_bytes(substream); format_verb = lola_get_format_verb(substream); if (bufsize != str->bufsize || period_bytes != str->period_bytes || format_verb != str->format_verb) { str->bufsize = bufsize; str->period_bytes = period_bytes; str->format_verb = format_verb; err = lola_setup_periods(chip, pcm, substream, str); if (err < 0) return err; } err = lola_set_stream_config(chip, str, runtime->channels); if (err < 0) return err; return lola_setup_controller(chip, pcm, str); err = lola_setup_controller(chip, pcm, str); if (err < 0) { lola_stream_reset(chip, str); return err; } return 0; } static int lola_pcm_trigger(struct snd_pcm_substream *substream, int cmd) Loading