Hello.
I post to ask if there is any progress on this bug ?
I saw the bug some time ago but it still exists on 2.6.24-rc2 and it is
annoying to run "rmmod snd-hda-intel" before i need to power off the machine.
My motherboard is not the same as the original poster's.
Mine is the Asus P5AD2 Premium and my codec is the Cmedia CMI9880
I run slackware too like the original poster but it is coincidence
since i reproduced it in debian 32bit and sabayon 64bit too.
I guess not many people have this issue that is why it hasn't been resolved
till now. So i tried to bisect the kernel to see which commit causes it.
I remember that the last working kernel was 2.6.13.
I had the impression that 2.6.14-rc1 introduced the bug so i bisected
the changes from 2.6.13 to 2.6.14-rc1 with no success of course because
the bug was actually introduced in 2.6.14-rc2 (i guess i remembered wrong).
I bisected the changes from 2.6.14-rc1 to 2.6.14-rc2 and git showed the
patch i include as "alsa-faulty-2.6.14-rc1-rc2.diff" to be the cause.
I compiled two kernels. One the vanilla 2.6.14-rc1 and one with this
patch applied and indeed it is the patch that causes the problem.
Then, i tried to remove the changes from the 2.6.24-rc2 i run now.
Some hunks of code didn't exist in 2.6.24-rc2, so i tried what existed.
I tried all the hunks one by one to see if maybe only a part of the
patch breaks the driver and indeed only one hunk is the problematic.
--- hda_intel.c.orig 2007-11-26 11:49:00.000000000 +0200
+++ hda_intel.c 2007-11-26 15:00:37.000000000 +0200
@@ -1004,10 +1004,11 @@
/* upper BDL address */
azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl_addr));
- /* enable the position buffer */
- if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
- azx_writel(chip, DPLBASE,
- (u32)chip->posbuf.addr |ICH6_DPLBASE_ENABLE);
+ if (chip->position_fix == POS_FIX_POSBUF) {
+ /* enable the position buffer */
+ if (! (azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
+ azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE);
+ }
/* set the interrupt enable bits in the descriptor control register */
azx_sd_writel(azx_dev, SD_CTL,
The above is the patch to make poweroff work again in 2.6.24-rc2.
I don't understand what the azx_readl,azx_writel functions do, but
with this patch applied everything works ok.
Can Mr. Takashi Iwai or anyone else that has knowledge about this,
see if this patch i include is correct or not and if it is correct
to include it in the kernel ?
Thank you for your time.
commit 0be3b5d3fb94c36c517655d18a936681d7108667
Author: Takashi Iwai <tiwai@xxxxxxx>
Date: Mon Sep 5 17:11:40 2005 +0200
[ALSA] hda-intel - Check validity of DMA position
HDA Intel driver
Check the validity of the current DMA position when position_fix=0 (auto)
is set. If the DMA position overcomes the threshold, the driver changes
the fix behavior automatically to use POSBUF.
Signed-off-by: Takashi Iwai <tiwai@xxxxxxx>
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 15107df..96f9e87 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -62,7 +62,7 @@ MODULE_PARM_DESC(enable, "Enable Intel H
module_param_array(model, charp, NULL, 0444);
MODULE_PARM_DESC(model, "Use the given board model.");
module_param_array(position_fix, int, NULL, 0444);
-MODULE_PARM_DESC(position_fix, "Fix DMA pointer (0 = FIFO size, 1 = none, 2 = POSBUF).");
+MODULE_PARM_DESC(position_fix, "Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size).");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"
@@ -211,9 +211,10 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO
/* position fix mode */
enum {
- POS_FIX_FIFO,
+ POS_FIX_AUTO,
POS_FIX_NONE,
- POS_FIX_POSBUF
+ POS_FIX_POSBUF,
+ POS_FIX_FIFO,
};
/* Defines for ATI HD Audio support in SB450 south bridge */
@@ -243,6 +244,7 @@ struct snd_azx_dev {
unsigned int fragsize; /* size of each period in bytes */
unsigned int frags; /* number for period in the play buffer */
unsigned int fifo_size; /* FIFO size */
+ unsigned int last_pos; /* last updated period position */
void __iomem *sd_addr; /* stream descriptor pointer */
@@ -256,6 +258,7 @@ struct snd_azx_dev {
unsigned int opened: 1;
unsigned int running: 1;
+ unsigned int period_updating: 1;
};
/* CORB/RIRB */
@@ -724,11 +727,9 @@ static void azx_init_chip(azx_t *chip)
/* initialize the codec command I/O */
azx_init_cmd_io(chip);
- if (chip->position_fix == POS_FIX_POSBUF) {
- /* program the position buffer */
- azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr);
- azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr));
- }
+ /* program the position buffer */
+ azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr);
+ azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr));
/* For ATI SB450 azalia HD audio, we need to enable snoop */
if (chip->driver_type == AZX_DRIVER_ATI) {
@@ -763,9 +764,11 @@ static irqreturn_t azx_interrupt(int irq
if (status & azx_dev->sd_int_sta_mask) {
azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK);
if (azx_dev->substream && azx_dev->running) {
+ azx_dev->period_updating = 1;
spin_unlock(&chip->reg_lock);
snd_pcm_period_elapsed(azx_dev->substream);
spin_lock(&chip->reg_lock);
+ azx_dev->period_updating = 0;
}
}
}
@@ -866,11 +869,9 @@ static int azx_setup_controller(azx_t *c
/* upper BDL address */
azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl_addr));
- if (chip->position_fix == POS_FIX_POSBUF) {
- /* enable the position buffer */
- if (! (azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
- azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE);
- }
+ /* enable the position buffer */
+ if (! (azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
+ azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE);
/* set the interrupt enable bits in the descriptor control register */
azx_sd_writel(azx_dev, SD_CTL, azx_sd_readl(azx_dev, SD_CTL) | SD_INT_MASK);
@@ -1078,6 +1079,7 @@ static int azx_pcm_prepare(snd_pcm_subst
azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1;
else
azx_dev->fifo_size = 0;
+ azx_dev->last_pos = 0;
return hinfo->ops.prepare(hinfo, apcm->codec, azx_dev->stream_tag,
azx_dev->format_val, substream);
@@ -1133,6 +1135,26 @@ static snd_pcm_uframes_t azx_pcm_pointer
pos = azx_sd_readl(azx_dev, SD_LPIB);
if (chip->position_fix == POS_FIX_FIFO)
pos += azx_dev->fifo_size;
+ else if (chip->position_fix == POS_FIX_AUTO && azx_dev->period_updating) {
+ /* check the validity of DMA position */
+ unsigned int diff = 0;
+ azx_dev->last_pos += azx_dev->fragsize;
+ if (azx_dev->last_pos > pos)
+ diff = azx_dev->last_pos - pos;
+ if (azx_dev->last_pos >= azx_dev->bufsize) {
+ if (pos < azx_dev->fragsize)
+ diff = 0;
+ azx_dev->last_pos = 0;
+ }
+ if (diff > 0 && diff <= azx_dev->fifo_size)
+ pos += azx_dev->fifo_size;
+ else {
+ snd_printdd(KERN_INFO "hda_intel: DMA position fix %d, switching to posbuf\n", diff);
+ chip->position_fix = POS_FIX_POSBUF;
+ pos = *azx_dev->posbuf;
+ }
+ azx_dev->period_updating = 0;
+ }
}
if (pos >= azx_dev->bufsize)
pos = 0;
@@ -1244,8 +1266,7 @@ static int __devinit azx_init_stream(azx
azx_dev_t *azx_dev = &chip->azx_dev[i];
azx_dev->bdl = (u32 *)(chip->bdl.area + off);
azx_dev->bdl_addr = chip->bdl.addr + off;
- if (chip->position_fix == POS_FIX_POSBUF)
- azx_dev->posbuf = (volatile u32 *)(chip->posbuf.area + i * 8);
+ azx_dev->posbuf = (volatile u32 *)(chip->posbuf.area + i * 8);
/* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */
azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80);
/* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */
@@ -1437,13 +1458,11 @@ static int __devinit azx_create(snd_card
snd_printk(KERN_ERR SFX "cannot allocate BDL\n");
goto errout;
}
- if (chip->position_fix == POS_FIX_POSBUF) {
- /* allocate memory for the position buffer */
- if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
- chip->num_streams * 8, &chip->posbuf)) < 0) {
- snd_printk(KERN_ERR SFX "cannot allocate posbuf\n");
- goto errout;
- }
+ /* allocate memory for the position buffer */
+ if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
+ chip->num_streams * 8, &chip->posbuf)) < 0) {
+ snd_printk(KERN_ERR SFX "cannot allocate posbuf\n");
+ goto errout;
}
/* allocate CORB/RIRB */
if ((err = azx_alloc_cmd_io(chip)) < 0)
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Alsa-user mailing list
Alsa-user@xxxxxxxxxxxxxxxxxxxxx
https://lists.sourceforge.net/lists/listinfo/alsa-user