From 8840ec0e7a869600a566984b765ea88067948b6a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 14 Apr 2009 14:51:04 +0200 Subject: [PATCH] --- yaml --- r: 143364 b: refs/heads/master c: bfb53037c61ddf7c16a40297ad16f2bcbde534dc h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/include/sound/pcm.h | 3 +- trunk/sound/core/pcm_lib.c | 47 +++------------ trunk/sound/pci/hda/hda_intel.c | 39 +++++-------- trunk/sound/pci/hda/patch_realtek.c | 5 +- trunk/sound/pci/intel8x0.c | 91 +++++++---------------------- 6 files changed, 47 insertions(+), 140 deletions(-) diff --git a/[refs] b/[refs] index 7427af89bf65..132b090a5bc7 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 45c27fc8c89d39956930abeff8433c33d07a8d5f +refs/heads/master: bfb53037c61ddf7c16a40297ad16f2bcbde534dc diff --git a/trunk/include/sound/pcm.h b/trunk/include/sound/pcm.h index c17296891617..8904b1900d7f 100644 --- a/trunk/include/sound/pcm.h +++ b/trunk/include/sound/pcm.h @@ -268,8 +268,7 @@ struct snd_pcm_runtime { int overrange; snd_pcm_uframes_t avail_max; snd_pcm_uframes_t hw_ptr_base; /* Position at buffer restart */ - snd_pcm_uframes_t hw_ptr_interrupt; /* Position at interrupt time */ - unsigned long hw_ptr_jiffies; /* Time when hw_ptr is updated */ + snd_pcm_uframes_t hw_ptr_interrupt; /* Position at interrupt time*/ /* -- HW params -- */ snd_pcm_access_t access; /* access mode */ diff --git a/trunk/sound/core/pcm_lib.c b/trunk/sound/core/pcm_lib.c index 63d088f2265f..fbb2e391591e 100644 --- a/trunk/sound/core/pcm_lib.c +++ b/trunk/sound/core/pcm_lib.c @@ -209,11 +209,9 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_uframes_t pos; - snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_ptr_interrupt, hw_base; - snd_pcm_sframes_t hdelta, delta; - unsigned long jdelta; + snd_pcm_uframes_t new_hw_ptr, hw_ptr_interrupt, hw_base; + snd_pcm_sframes_t delta; - old_hw_ptr = runtime->status->hw_ptr; pos = snd_pcm_update_hw_ptr_pos(substream, runtime); if (pos == SNDRV_PCM_POS_XRUN) { xrun(substream); @@ -249,30 +247,7 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream) new_hw_ptr = hw_base + pos; } } - hdelta = new_hw_ptr - old_hw_ptr; - jdelta = jiffies - runtime->hw_ptr_jiffies; - if (((hdelta * HZ) / runtime->rate) > jdelta + HZ/100) { - delta = jdelta / - (((runtime->period_size * HZ) / runtime->rate) - + HZ/100); - hw_ptr_error(substream, - "hw_ptr skipping! [Q] " - "(pos=%ld, delta=%ld, period=%ld, " - "jdelta=%lu/%lu/%lu)\n", - (long)pos, (long)hdelta, - (long)runtime->period_size, jdelta, - ((hdelta * HZ) / runtime->rate), delta); - hw_ptr_interrupt = runtime->hw_ptr_interrupt + - runtime->period_size * delta; - if (hw_ptr_interrupt >= runtime->boundary) - hw_ptr_interrupt -= runtime->boundary; - /* rebase to interrupt position */ - hw_base = new_hw_ptr = hw_ptr_interrupt; - /* align hw_base to buffer_size */ - hw_base -= hw_base % runtime->buffer_size; - delta = 0; - } - if (delta > runtime->period_size + runtime->period_size / 2) { + if (delta > runtime->period_size) { hw_ptr_error(substream, "Lost interrupts? " "(stream=%i, delta=%ld, intr_ptr=%ld)\n", @@ -288,7 +263,6 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream) runtime->hw_ptr_base = hw_base; runtime->status->hw_ptr = new_hw_ptr; - runtime->hw_ptr_jiffies = jiffies; runtime->hw_ptr_interrupt = hw_ptr_interrupt; return snd_pcm_update_hw_ptr_post(substream, runtime); @@ -301,7 +275,6 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream) snd_pcm_uframes_t pos; snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_base; snd_pcm_sframes_t delta; - unsigned long jdelta; old_hw_ptr = runtime->status->hw_ptr; pos = snd_pcm_update_hw_ptr_pos(substream, runtime); @@ -313,15 +286,14 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream) new_hw_ptr = hw_base + pos; delta = new_hw_ptr - old_hw_ptr; - jdelta = jiffies - runtime->hw_ptr_jiffies; if (delta < 0) { delta += runtime->buffer_size; if (delta < 0) { hw_ptr_error(substream, "Unexpected hw_pointer value [2] " - "(stream=%i, pos=%ld, old_ptr=%ld, jdelta=%li)\n", + "(stream=%i, pos=%ld, old_ptr=%ld)\n", substream->stream, (long)pos, - (long)old_hw_ptr, jdelta); + (long)old_hw_ptr); return 0; } hw_base += runtime->buffer_size; @@ -329,13 +301,12 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream) hw_base = 0; new_hw_ptr = hw_base + pos; } - if (((delta * HZ) / runtime->rate) > jdelta + HZ/100) { + if (delta > runtime->period_size && runtime->periods > 1) { hw_ptr_error(substream, "hw_ptr skipping! " - "(pos=%ld, delta=%ld, period=%ld, jdelta=%lu/%lu)\n", + "(pos=%ld, delta=%ld, period=%ld)\n", (long)pos, (long)delta, - (long)runtime->period_size, jdelta, - ((delta * HZ) / runtime->rate)); + (long)runtime->period_size); return 0; } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && @@ -344,7 +315,6 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream) runtime->hw_ptr_base = hw_base; runtime->status->hw_ptr = new_hw_ptr; - runtime->hw_ptr_jiffies = jiffies; return snd_pcm_update_hw_ptr_post(substream, runtime); } @@ -1471,7 +1441,6 @@ static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream, runtime->status->hw_ptr %= runtime->buffer_size; else runtime->status->hw_ptr = 0; - runtime->hw_ptr_jiffies = jiffies; snd_pcm_stream_unlock_irqrestore(substream, flags); return 0; } diff --git a/trunk/sound/pci/hda/hda_intel.c b/trunk/sound/pci/hda/hda_intel.c index bc882f8f163c..7ba8db5d4c42 100644 --- a/trunk/sound/pci/hda/hda_intel.c +++ b/trunk/sound/pci/hda/hda_intel.c @@ -312,9 +312,6 @@ struct azx_dev { unsigned int period_bytes; /* size of the period in bytes */ unsigned int frags; /* number for period in the play buffer */ unsigned int fifo_size; /* FIFO size */ - unsigned int start_flag: 1; /* stream full start flag */ - unsigned long start_jiffies; /* start + minimum jiffies */ - unsigned long min_jiffies; /* minimum jiffies before position is valid */ void __iomem *sd_addr; /* stream descriptor pointer */ @@ -333,6 +330,7 @@ struct azx_dev { unsigned int opened :1; unsigned int running :1; unsigned int irq_pending :1; + unsigned int irq_ignore :1; /* * For VIA: * A flag to ensure DMA position is 0 @@ -977,7 +975,7 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id) struct azx *chip = dev_id; struct azx_dev *azx_dev; u32 status; - int i, ok; + int i; spin_lock(&chip->reg_lock); @@ -993,14 +991,18 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id) azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK); if (!azx_dev->substream || !azx_dev->running) continue; + /* ignore the first dummy IRQ (due to pos_adj) */ + if (azx_dev->irq_ignore) { + azx_dev->irq_ignore = 0; + continue; + } /* check whether this IRQ is really acceptable */ - ok = azx_position_ok(chip, azx_dev); - if (ok == 1) { + if (azx_position_ok(chip, azx_dev)) { azx_dev->irq_pending = 0; spin_unlock(&chip->reg_lock); snd_pcm_period_elapsed(azx_dev->substream); spin_lock(&chip->reg_lock); - } else if (ok == 0 && chip->bus && chip->bus->workq) { + } else if (chip->bus && chip->bus->workq) { /* bogus IRQ, process it later */ azx_dev->irq_pending = 1; queue_work(chip->bus->workq, @@ -1086,6 +1088,7 @@ static int azx_setup_periods(struct azx *chip, bdl = (u32 *)azx_dev->bdl.area; ofs = 0; azx_dev->frags = 0; + azx_dev->irq_ignore = 0; pos_adj = bdl_pos_adj[chip->dev_index]; if (pos_adj > 0) { struct snd_pcm_runtime *runtime = substream->runtime; @@ -1106,6 +1109,7 @@ static int azx_setup_periods(struct azx *chip, &bdl, ofs, pos_adj, 1); if (ofs < 0) goto error; + azx_dev->irq_ignore = 1; } } else pos_adj = 0; @@ -1151,9 +1155,6 @@ static void azx_stream_reset(struct azx *chip, struct azx_dev *azx_dev) while (((val = azx_sd_readb(azx_dev, SD_CTL)) & SD_CTL_STREAM_RESET) && --timeout) ; - - /* reset first position - may not be synced with hw at this time */ - *azx_dev->posbuf = 0; } /* @@ -1408,6 +1409,7 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) snd_pcm_set_sync(substream); mutex_unlock(&chip->open_mutex); + azx_stream_reset(chip, azx_dev); return 0; } @@ -1472,7 +1474,6 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) unsigned int bufsize, period_bytes, format_val; int err; - azx_stream_reset(chip, azx_dev); format_val = snd_hda_calc_stream_format(runtime->rate, runtime->channels, runtime->format, @@ -1501,8 +1502,6 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) return err; } - azx_dev->min_jiffies = (runtime->period_size * HZ) / - (runtime->rate * 2); azx_setup_controller(chip, azx_dev); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1; @@ -1519,14 +1518,13 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) struct azx *chip = apcm->chip; struct azx_dev *azx_dev; struct snd_pcm_substream *s; - int rstart = 0, start, nsync = 0, sbits = 0; + int start, nsync = 0, sbits = 0; int nwait, timeout; switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - rstart = 1; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_START: start = 1; break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: @@ -1556,10 +1554,6 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) if (s->pcm->card != substream->pcm->card) continue; azx_dev = get_azx_dev(s); - if (rstart) { - azx_dev->start_flag = 1; - azx_dev->start_jiffies = jiffies + azx_dev->min_jiffies; - } if (start) azx_stream_start(chip, azx_dev); else @@ -1709,11 +1703,6 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) { unsigned int pos; - if (azx_dev->start_flag && - time_before_eq(jiffies, azx_dev->start_jiffies)) - return -1; /* bogus (too early) interrupt */ - azx_dev->start_flag = 0; - pos = azx_get_position(chip, azx_dev); if (chip->position_fix == POS_FIX_AUTO) { if (!pos) { diff --git a/trunk/sound/pci/hda/patch_realtek.c b/trunk/sound/pci/hda/patch_realtek.c index f35e58a2d921..6ed787eedd06 100644 --- a/trunk/sound/pci/hda/patch_realtek.c +++ b/trunk/sound/pci/hda/patch_realtek.c @@ -8742,10 +8742,9 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC883_LAPTOP_EAPD), SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch), SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION), - SND_PCI_QUIRK(0x1734, 0x1107, "FSC AMILO Xi2550", + SND_PCI_QUIRK_MASK(0x1734, 0xfff0, 0x1100, "FSC AMILO Xi/Pi25xx", ALC883_FUJITSU_PI2515), - SND_PCI_QUIRK(0x1734, 0x1108, "Fujitsu AMILO Pi2515", ALC883_FUJITSU_PI2515), - SND_PCI_QUIRK(0x1734, 0x113d, "Fujitsu AMILO Xa3530", + SND_PCI_QUIRK_MASK(0x1734, 0xfff0, 0x1130, "Fujitsu AMILO Xa35xx", ALC888_FUJITSU_XA3530), SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo 101e", ALC883_LENOVO_101E_2ch), SND_PCI_QUIRK(0x17aa, 0x2085, "Lenovo NB0763", ALC883_LENOVO_NB0763), diff --git a/trunk/sound/pci/intel8x0.c b/trunk/sound/pci/intel8x0.c index 5dced5b79387..57648810eaf1 100644 --- a/trunk/sound/pci/intel8x0.c +++ b/trunk/sound/pci/intel8x0.c @@ -355,9 +355,6 @@ struct ichdev { unsigned int fragsize1; unsigned int position; unsigned int pos_shift; - unsigned int last_pos; - unsigned long last_pos_jiffies; - unsigned int jiffy_to_bytes; int frags; int lvi; int lvi_frag; @@ -841,10 +838,7 @@ static int snd_intel8x0_pcm_trigger(struct snd_pcm_substream *substream, int cmd ichdev->suspended = 0; /* fallthru */ case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: val = ICH_IOCE | ICH_STARTBM; - ichdev->last_pos = ichdev->position; - ichdev->last_pos_jiffies = jiffies; break; case SNDRV_PCM_TRIGGER_SUSPEND: ichdev->suspended = 1; @@ -855,6 +849,9 @@ static int snd_intel8x0_pcm_trigger(struct snd_pcm_substream *substream, int cmd case SNDRV_PCM_TRIGGER_PAUSE_PUSH: val = ICH_IOCE; break; + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + val = ICH_IOCE | ICH_STARTBM; + break; default: return -EINVAL; } @@ -1048,7 +1045,6 @@ static int snd_intel8x0_pcm_prepare(struct snd_pcm_substream *substream) ichdev->pos_shift = (runtime->sample_bits > 16) ? 2 : 1; } snd_intel8x0_setup_periods(chip, ichdev); - ichdev->jiffy_to_bytes = (runtime->rate * 4 * ichdev->pos_shift) / HZ; return 0; } @@ -1057,7 +1053,7 @@ static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(struct snd_pcm_substream *subs struct intel8x0 *chip = snd_pcm_substream_chip(substream); struct ichdev *ichdev = get_ichdev(substream); size_t ptr1, ptr; - int civ, timeout = 10; + int civ, timeout = 100; unsigned int position; spin_lock(&chip->reg_lock); @@ -1073,19 +1069,9 @@ static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(struct snd_pcm_substream *subs ptr1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb)) break; } while (timeout--); - if (ptr1 != 0) { - ptr1 <<= ichdev->pos_shift; - ptr = ichdev->fragsize1 - ptr1; - ptr += position; - ichdev->last_pos = ptr; - ichdev->last_pos_jiffies = jiffies; - } else { - ptr1 = jiffies - ichdev->last_pos_jiffies; - if (ptr1) - ptr1 -= 1; - ptr = ichdev->last_pos + ptr1 * ichdev->jiffy_to_bytes; - ptr %= ichdev->size; - } + ptr1 <<= ichdev->pos_shift; + ptr = ichdev->fragsize1 - ptr1; + ptr += position; spin_unlock(&chip->reg_lock); if (ptr >= ichdev->size) return 0; @@ -2675,14 +2661,12 @@ static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip) struct snd_pcm_substream *subs; struct ichdev *ichdev; unsigned long port; - unsigned long pos, pos1, t; - int civ, timeout = 1000, attempt = 1; - struct timespec start_time, stop_time; + unsigned long pos, t; + struct timeval start_time, stop_time; if (chip->ac97_bus->clock != 48000) return; /* specified in module option */ - __again: subs = chip->pcm[0]->streams[0].substream; if (! subs || subs->dma_buffer.bytes < INTEL8X0_TESTBUF_SIZE) { snd_printk(KERN_WARNING "no playback buffer allocated - aborting measure ac97 clock\n"); @@ -2690,7 +2674,7 @@ static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip) } ichdev = &chip->ichd[ICHD_PCMOUT]; ichdev->physbuf = subs->dma_buffer.addr; - ichdev->size = ichdev->fragsize = INTEL8X0_TESTBUF_SIZE; + ichdev->size = chip->ichd[ICHD_PCMOUT].fragsize = INTEL8X0_TESTBUF_SIZE; ichdev->substream = NULL; /* don't process interrupts */ /* set rate */ @@ -2709,31 +2693,16 @@ static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip) iputbyte(chip, port + ICH_REG_OFF_CR, ICH_IOCE); iputdword(chip, ICHREG(ALI_DMACR), 1 << ichdev->ali_slot); } - do_posix_clock_monotonic_gettime(&start_time); + do_gettimeofday(&start_time); spin_unlock_irq(&chip->reg_lock); msleep(50); spin_lock_irq(&chip->reg_lock); /* check the position */ - do { - civ = igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV); - pos1 = igetword(chip, ichdev->reg_offset + ichdev->roff_picb); - if (pos1 == 0) { - udelay(10); - continue; - } - if (civ == igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV) && - pos1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb)) - break; - } while (timeout--); - if (pos1 == 0) { /* oops, this value is not reliable */ - pos = 0; - } else { - pos = ichdev->fragsize1; - pos -= pos1 << ichdev->pos_shift; - pos += ichdev->position; - } + pos = ichdev->fragsize1; + pos -= igetword(chip, ichdev->reg_offset + ichdev->roff_picb) << ichdev->pos_shift; + pos += ichdev->position; chip->in_measurement = 0; - do_posix_clock_monotonic_gettime(&stop_time); + do_gettimeofday(&stop_time); /* stop */ if (chip->device_type == DEVICE_ALI) { iputdword(chip, ICHREG(ALI_DMACR), 1 << (ichdev->ali_slot + 16)); @@ -2748,37 +2717,19 @@ static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip) iputbyte(chip, port + ICH_REG_OFF_CR, ICH_RESETREGS); spin_unlock_irq(&chip->reg_lock); - if (pos == 0) { - snd_printk(KERN_ERR "intel8x0: measure - unreliable DMA position..\n"); - __retry: - if (attempt < 2) { - attempt++; - goto __again; - } - return; - } - - pos /= 4; t = stop_time.tv_sec - start_time.tv_sec; t *= 1000000; - t += (stop_time.tv_nsec - start_time.tv_nsec) / 1000; - printk(KERN_INFO "%s: measured %lu usecs (%lu samples)\n", __func__, t, pos); + t += stop_time.tv_usec - start_time.tv_usec; + printk(KERN_INFO "%s: measured %lu usecs\n", __func__, t); if (t == 0) { - snd_printk(KERN_ERR "intel8x0: ?? calculation error..\n"); - goto __retry; + snd_printk(KERN_ERR "?? calculation error..\n"); + return; } - pos *= 1000; + pos = (pos / 4) * 1000; pos = (pos / t) * 1000 + ((pos % t) * 1000) / t; - if (pos < 40000 || pos >= 60000) { + if (pos < 40000 || pos >= 60000) /* abnormal value. hw problem? */ printk(KERN_INFO "intel8x0: measured clock %ld rejected\n", pos); - goto __retry; - } else if (pos > 40500 && pos < 41500) - /* first exception - 41000Hz reference clock */ - chip->ac97_bus->clock = 41000; - else if (pos > 43600 && pos < 44600) - /* second exception - 44100HZ reference clock */ - chip->ac97_bus->clock = 44100; else if (pos < 47500 || pos > 48500) /* not 48000Hz, tuning the clock.. */ chip->ac97_bus->clock = (chip->ac97_bus->clock * 48000) / pos;