Loading sound/pci/hda/hda_intel.c +79 −17 Original line number Diff line number Diff line Loading @@ -221,6 +221,9 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; /* SD_CTL bits */ #define SD_CTL_STREAM_RESET 0x01 /* stream reset bit */ #define SD_CTL_DMA_START 0x02 /* stream DMA start bit */ #define SD_CTL_STRIPE (3 << 16) /* stripe control */ #define SD_CTL_TRAFFIC_PRIO (1 << 18) /* traffic priority */ #define SD_CTL_DIR (1 << 19) /* bi-directional stream */ #define SD_CTL_STREAM_TAG_MASK (0xf << 20) #define SD_CTL_STREAM_TAG_SHIFT 20 Loading Loading @@ -1180,7 +1183,8 @@ static struct snd_pcm_hardware azx_pcm_hw = { SNDRV_PCM_INFO_MMAP_VALID | /* No full-resume yet implemented */ /* SNDRV_PCM_INFO_RESUME |*/ SNDRV_PCM_INFO_PAUSE), SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_SYNC_START), .formats = SNDRV_PCM_FMTBIT_S16_LE, .rates = SNDRV_PCM_RATE_48000, .rate_min = 48000, Loading Loading @@ -1242,6 +1246,7 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) spin_unlock_irqrestore(&chip->reg_lock, flags); runtime->private_data = azx_dev; snd_pcm_set_sync(substream); mutex_unlock(&chip->open_mutex); return 0; } Loading Loading @@ -1326,37 +1331,94 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) { struct azx_pcm *apcm = snd_pcm_substream_chip(substream); struct azx_dev *azx_dev = get_azx_dev(substream); struct azx *chip = apcm->chip; int err = 0; struct azx_dev *azx_dev; struct snd_pcm_substream *s; int start, nsync = 0, sbits = 0; int nwait, timeout; spin_lock(&chip->reg_lock); switch (cmd) { case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_START: azx_stream_start(chip, azx_dev); azx_dev->running = 1; start = 1; break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_STOP: azx_stream_stop(chip, azx_dev); azx_dev->running = 0; start = 0; break; default: err = -EINVAL; return -EINVAL; } snd_pcm_group_for_each_entry(s, substream) { if (s->pcm->card != substream->pcm->card) continue; azx_dev = get_azx_dev(s); sbits |= 1 << azx_dev->index; nsync++; snd_pcm_trigger_done(s, substream); } spin_lock(&chip->reg_lock); if (nsync > 1) { /* first, set SYNC bits of corresponding streams */ azx_writel(chip, SYNC, azx_readl(chip, SYNC) | sbits); } snd_pcm_group_for_each_entry(s, substream) { if (s->pcm->card != substream->pcm->card) continue; azx_dev = get_azx_dev(s); if (start) azx_stream_start(chip, azx_dev); else azx_stream_stop(chip, azx_dev); azx_dev->running = start; } spin_unlock(&chip->reg_lock); if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH || cmd == SNDRV_PCM_TRIGGER_SUSPEND || cmd == SNDRV_PCM_TRIGGER_STOP) { int timeout = 5000; while ((azx_sd_readb(azx_dev, SD_CTL) & SD_CTL_DMA_START) && --timeout) ; if (start) { if (nsync == 1) return 0; /* wait until all FIFOs get ready */ for (timeout = 5000; timeout; timeout--) { nwait = 0; snd_pcm_group_for_each_entry(s, substream) { if (s->pcm->card != substream->pcm->card) continue; azx_dev = get_azx_dev(s); if (!(azx_sd_readb(azx_dev, SD_STS) & SD_STS_FIFO_READY)) nwait++; } return err; if (!nwait) break; cpu_relax(); } } else { /* wait until all RUN bits are cleared */ for (timeout = 5000; timeout; timeout--) { nwait = 0; snd_pcm_group_for_each_entry(s, substream) { if (s->pcm->card != substream->pcm->card) continue; azx_dev = get_azx_dev(s); if (azx_sd_readb(azx_dev, SD_CTL) & SD_CTL_DMA_START) nwait++; } if (!nwait) break; cpu_relax(); } } if (nsync > 1) { spin_lock(&chip->reg_lock); /* reset SYNC bits */ azx_writel(chip, SYNC, azx_readl(chip, SYNC) & ~sbits); spin_unlock(&chip->reg_lock); } return 0; } static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream) Loading Loading
sound/pci/hda/hda_intel.c +79 −17 Original line number Diff line number Diff line Loading @@ -221,6 +221,9 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; /* SD_CTL bits */ #define SD_CTL_STREAM_RESET 0x01 /* stream reset bit */ #define SD_CTL_DMA_START 0x02 /* stream DMA start bit */ #define SD_CTL_STRIPE (3 << 16) /* stripe control */ #define SD_CTL_TRAFFIC_PRIO (1 << 18) /* traffic priority */ #define SD_CTL_DIR (1 << 19) /* bi-directional stream */ #define SD_CTL_STREAM_TAG_MASK (0xf << 20) #define SD_CTL_STREAM_TAG_SHIFT 20 Loading Loading @@ -1180,7 +1183,8 @@ static struct snd_pcm_hardware azx_pcm_hw = { SNDRV_PCM_INFO_MMAP_VALID | /* No full-resume yet implemented */ /* SNDRV_PCM_INFO_RESUME |*/ SNDRV_PCM_INFO_PAUSE), SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_SYNC_START), .formats = SNDRV_PCM_FMTBIT_S16_LE, .rates = SNDRV_PCM_RATE_48000, .rate_min = 48000, Loading Loading @@ -1242,6 +1246,7 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) spin_unlock_irqrestore(&chip->reg_lock, flags); runtime->private_data = azx_dev; snd_pcm_set_sync(substream); mutex_unlock(&chip->open_mutex); return 0; } Loading Loading @@ -1326,37 +1331,94 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) { struct azx_pcm *apcm = snd_pcm_substream_chip(substream); struct azx_dev *azx_dev = get_azx_dev(substream); struct azx *chip = apcm->chip; int err = 0; struct azx_dev *azx_dev; struct snd_pcm_substream *s; int start, nsync = 0, sbits = 0; int nwait, timeout; spin_lock(&chip->reg_lock); switch (cmd) { case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_START: azx_stream_start(chip, azx_dev); azx_dev->running = 1; start = 1; break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_STOP: azx_stream_stop(chip, azx_dev); azx_dev->running = 0; start = 0; break; default: err = -EINVAL; return -EINVAL; } snd_pcm_group_for_each_entry(s, substream) { if (s->pcm->card != substream->pcm->card) continue; azx_dev = get_azx_dev(s); sbits |= 1 << azx_dev->index; nsync++; snd_pcm_trigger_done(s, substream); } spin_lock(&chip->reg_lock); if (nsync > 1) { /* first, set SYNC bits of corresponding streams */ azx_writel(chip, SYNC, azx_readl(chip, SYNC) | sbits); } snd_pcm_group_for_each_entry(s, substream) { if (s->pcm->card != substream->pcm->card) continue; azx_dev = get_azx_dev(s); if (start) azx_stream_start(chip, azx_dev); else azx_stream_stop(chip, azx_dev); azx_dev->running = start; } spin_unlock(&chip->reg_lock); if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH || cmd == SNDRV_PCM_TRIGGER_SUSPEND || cmd == SNDRV_PCM_TRIGGER_STOP) { int timeout = 5000; while ((azx_sd_readb(azx_dev, SD_CTL) & SD_CTL_DMA_START) && --timeout) ; if (start) { if (nsync == 1) return 0; /* wait until all FIFOs get ready */ for (timeout = 5000; timeout; timeout--) { nwait = 0; snd_pcm_group_for_each_entry(s, substream) { if (s->pcm->card != substream->pcm->card) continue; azx_dev = get_azx_dev(s); if (!(azx_sd_readb(azx_dev, SD_STS) & SD_STS_FIFO_READY)) nwait++; } return err; if (!nwait) break; cpu_relax(); } } else { /* wait until all RUN bits are cleared */ for (timeout = 5000; timeout; timeout--) { nwait = 0; snd_pcm_group_for_each_entry(s, substream) { if (s->pcm->card != substream->pcm->card) continue; azx_dev = get_azx_dev(s); if (azx_sd_readb(azx_dev, SD_CTL) & SD_CTL_DMA_START) nwait++; } if (!nwait) break; cpu_relax(); } } if (nsync > 1) { spin_lock(&chip->reg_lock); /* reset SYNC bits */ azx_writel(chip, SYNC, azx_readl(chip, SYNC) & ~sbits); spin_unlock(&chip->reg_lock); } return 0; } static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream) Loading