Subject: [PATCH] ALSA: Don't cold reset AC97 codecs in some ICH chipsets

Check in a quirk list if it should do cold reset when AC97 power saving
is enabled. Some devices do not resume properly when cold reset,
although power saving works OK.

Signed-off-by: Thadeu Lima de Souza Cascardo <[email protected]>
---
sound/pci/intel8x0.c | 68 ++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 52 insertions(+), 16 deletions(-)

diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index 19d3391..b37bd26 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -2287,23 +2287,23 @@ static void do_ali_reset(struct intel8x0 *chip)
iputdword(chip, ICHREG(ALI_INTERRUPTSR), 0x00000000);
}

-static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing)
-{
- unsigned long end_time;
- unsigned int cnt, status, nstatus;
-
- /* put logic to right state */
- /* first clear status bits */
- status = ICH_RCS | ICH_MCINT | ICH_POINT | ICH_PIINT;
- if (chip->device_type == DEVICE_NFORCE)
- status |= ICH_NVSPINT;
- cnt = igetdword(chip, ICHREG(GLOB_STA));
- iputdword(chip, ICHREG(GLOB_STA), cnt & status);
+#ifdef CONFIG_SND_AC97_POWER_SAVE
+static struct snd_pci_quirk ich_chip_reset_mode[] = {
+ SND_PCI_QUIRK(0x1014, 0x051f, "Thinkpad R32", 1),
+ { } /* end */
+};

+static int snd_intel8x0_ich_chip_cold_reset(struct intel8x0 *chip)
+{
+ unsigned int cnt;
/* ACLink on, 2 channels */
+
+ if (snd_pci_quirk_lookup(chip->pci, ich_chip_reset_mode))
+ return -EIO;
+
cnt = igetdword(chip, ICHREG(GLOB_CNT));
cnt &= ~(ICH_ACLINK | ICH_PCM_246_MASK);
-#ifdef CONFIG_SND_AC97_POWER_SAVE
+
/* do cold reset - the full ac97 powerdown may leave the controller
* in a warm state but actually it cannot communicate with the codec.
*/
@@ -2312,22 +2312,58 @@ static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing)
udelay(10);
iputdword(chip, ICHREG(GLOB_CNT), cnt | ICH_AC97COLD);
msleep(1);
+ return 0;
+}
+#define snd_intel8x0_ich_chip_can_cold_reset(chip) \
+ (!snd_pci_quirk_lookup(chip->pci, ich_chip_reset_mode))
#else
+#define snd_intel8x0_ich_chip_cold_reset(x) do { } while (0)
+#define snd_intel8x0_ich_chip_can_cold_reset(chip) (0)
+#endif
+
+static int snd_intel8x0_ich_chip_reset(struct intel8x0 *chip)
+{
+ unsigned long end_time;
+ unsigned int cnt;
+ /* ACLink on, 2 channels */
+ cnt = igetdword(chip, ICHREG(GLOB_CNT));
+ cnt &= ~(ICH_ACLINK | ICH_PCM_246_MASK);
/* finish cold or do warm reset */
cnt |= (cnt & ICH_AC97COLD) == 0 ? ICH_AC97COLD : ICH_AC97WARM;
iputdword(chip, ICHREG(GLOB_CNT), cnt);
end_time = (jiffies + (HZ / 4)) + 1;
do {
if ((igetdword(chip, ICHREG(GLOB_CNT)) & ICH_AC97WARM) == 0)
- goto __ok;
+ return 0;
schedule_timeout_uninterruptible(1);
} while (time_after_eq(end_time, jiffies));
snd_printk(KERN_ERR "AC'97 warm reset still in progress? [0x%x]\n",
igetdword(chip, ICHREG(GLOB_CNT)));
return -EIO;
+}
+
+static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing)
+{
+ unsigned long end_time;
+ unsigned int status, nstatus;
+ unsigned int cnt;
+ int err;
+
+ /* put logic to right state */
+ /* first clear status bits */
+ status = ICH_RCS | ICH_MCINT | ICH_POINT | ICH_PIINT;
+ if (chip->device_type == DEVICE_NFORCE)
+ status |= ICH_NVSPINT;
+ cnt = igetdword(chip, ICHREG(GLOB_STA));
+ iputdword(chip, ICHREG(GLOB_STA), cnt & status);
+
+ if (snd_intel8x0_ich_chip_can_cold_reset(chip))
+ err = snd_intel8x0_ich_chip_cold_reset(chip);
+ else
+ err = snd_intel8x0_ich_chip_reset(chip);
+ if (err < 0)
+ return err;

- __ok:
-#endif
if (probing) {
/* wait for any codec ready status.
* Once it becomes ready it should remain ready
--
1.6.0.6


2009-01-28 15:20:28

by Takashi Iwai

[permalink] [raw]
Subject: Re: [PATCH] ALSA: Don't cold reset AC97 codecs in some ICH chipsets

At Wed, 28 Jan 2009 12:40:42 -0200,
Thadeu Lima de Souza Cascardo wrote:
>
> Check in a quirk list if it should do cold reset when AC97 power saving
> is enabled. Some devices do not resume properly when cold reset,
> although power saving works OK.
>
> Signed-off-by: Thadeu Lima de Souza Cascardo <[email protected]>

Thanks, applied now.

... and soon I found a build error when CONFIG_SND_AC97_POWERSAVE=n.
Fixed, too :)


Takashi

> ---
> sound/pci/intel8x0.c | 68 ++++++++++++++++++++++++++++++++++++++-----------
> 1 files changed, 52 insertions(+), 16 deletions(-)
>
> diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
> index 19d3391..b37bd26 100644
> --- a/sound/pci/intel8x0.c
> +++ b/sound/pci/intel8x0.c
> @@ -2287,23 +2287,23 @@ static void do_ali_reset(struct intel8x0 *chip)
> iputdword(chip, ICHREG(ALI_INTERRUPTSR), 0x00000000);
> }
>
> -static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing)
> -{
> - unsigned long end_time;
> - unsigned int cnt, status, nstatus;
> -
> - /* put logic to right state */
> - /* first clear status bits */
> - status = ICH_RCS | ICH_MCINT | ICH_POINT | ICH_PIINT;
> - if (chip->device_type == DEVICE_NFORCE)
> - status |= ICH_NVSPINT;
> - cnt = igetdword(chip, ICHREG(GLOB_STA));
> - iputdword(chip, ICHREG(GLOB_STA), cnt & status);
> +#ifdef CONFIG_SND_AC97_POWER_SAVE
> +static struct snd_pci_quirk ich_chip_reset_mode[] = {
> + SND_PCI_QUIRK(0x1014, 0x051f, "Thinkpad R32", 1),
> + { } /* end */
> +};
>
> +static int snd_intel8x0_ich_chip_cold_reset(struct intel8x0 *chip)
> +{
> + unsigned int cnt;
> /* ACLink on, 2 channels */
> +
> + if (snd_pci_quirk_lookup(chip->pci, ich_chip_reset_mode))
> + return -EIO;
> +
> cnt = igetdword(chip, ICHREG(GLOB_CNT));
> cnt &= ~(ICH_ACLINK | ICH_PCM_246_MASK);
> -#ifdef CONFIG_SND_AC97_POWER_SAVE
> +
> /* do cold reset - the full ac97 powerdown may leave the controller
> * in a warm state but actually it cannot communicate with the codec.
> */
> @@ -2312,22 +2312,58 @@ static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing)
> udelay(10);
> iputdword(chip, ICHREG(GLOB_CNT), cnt | ICH_AC97COLD);
> msleep(1);
> + return 0;
> +}
> +#define snd_intel8x0_ich_chip_can_cold_reset(chip) \
> + (!snd_pci_quirk_lookup(chip->pci, ich_chip_reset_mode))
> #else
> +#define snd_intel8x0_ich_chip_cold_reset(x) do { } while (0)
> +#define snd_intel8x0_ich_chip_can_cold_reset(chip) (0)
> +#endif
> +
> +static int snd_intel8x0_ich_chip_reset(struct intel8x0 *chip)
> +{
> + unsigned long end_time;
> + unsigned int cnt;
> + /* ACLink on, 2 channels */
> + cnt = igetdword(chip, ICHREG(GLOB_CNT));
> + cnt &= ~(ICH_ACLINK | ICH_PCM_246_MASK);
> /* finish cold or do warm reset */
> cnt |= (cnt & ICH_AC97COLD) == 0 ? ICH_AC97COLD : ICH_AC97WARM;
> iputdword(chip, ICHREG(GLOB_CNT), cnt);
> end_time = (jiffies + (HZ / 4)) + 1;
> do {
> if ((igetdword(chip, ICHREG(GLOB_CNT)) & ICH_AC97WARM) == 0)
> - goto __ok;
> + return 0;
> schedule_timeout_uninterruptible(1);
> } while (time_after_eq(end_time, jiffies));
> snd_printk(KERN_ERR "AC'97 warm reset still in progress? [0x%x]\n",
> igetdword(chip, ICHREG(GLOB_CNT)));
> return -EIO;
> +}
> +
> +static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing)
> +{
> + unsigned long end_time;
> + unsigned int status, nstatus;
> + unsigned int cnt;
> + int err;
> +
> + /* put logic to right state */
> + /* first clear status bits */
> + status = ICH_RCS | ICH_MCINT | ICH_POINT | ICH_PIINT;
> + if (chip->device_type == DEVICE_NFORCE)
> + status |= ICH_NVSPINT;
> + cnt = igetdword(chip, ICHREG(GLOB_STA));
> + iputdword(chip, ICHREG(GLOB_STA), cnt & status);
> +
> + if (snd_intel8x0_ich_chip_can_cold_reset(chip))
> + err = snd_intel8x0_ich_chip_cold_reset(chip);
> + else
> + err = snd_intel8x0_ich_chip_reset(chip);
> + if (err < 0)
> + return err;
>
> - __ok:
> -#endif
> if (probing) {
> /* wait for any codec ready status.
> * Once it becomes ready it should remain ready
> --
> 1.6.0.6
>

Subject: Re: [PATCH] ALSA: Don't cold reset AC97 codecs in some ICH chipsets

On Wed, Jan 28, 2009 at 04:20:12PM +0100, Takashi Iwai wrote:
> At Wed, 28 Jan 2009 12:40:42 -0200,
> Thadeu Lima de Souza Cascardo wrote:
> >
> > Check in a quirk list if it should do cold reset when AC97 power saving
> > is enabled. Some devices do not resume properly when cold reset,
> > although power saving works OK.
> >
> > Signed-off-by: Thadeu Lima de Souza Cascardo <[email protected]>
>
> Thanks, applied now.
>
> ... and soon I found a build error when CONFIG_SND_AC97_POWERSAVE=n.
> Fixed, too :)


Sorry for this one. I've cleaned the modules and built them again with a
changed config. Must have done something wrong in the build. Thanks for
the fix.

Regarding the warning fix in 92aab0a0, it is related to this commit:
248c982a, which was proposed by you during our previous discussion, and
didn't really fix my problem.

I've been watching your tree ever since and this patch has been in your
master branch since then, perhaps awaiting some conclusion about this
issue.

Do you think it solves any problems for other device models? In my case,
if the cold reset was done, this would simply not work.

Looking closer to the patch now, I see a point in keeping it, which may
be the reason you did so. It will make the resume faster in those cases
the init_bits are different from what the driver though would be there.

In this case, I think the log message should be more clear about that,
since it seems to indicate that the commit makes the driver wait for
more codecs (all codec slots) than before the commit.

Regards,
Cascardo.


Attachments:
(No filename) (1.52 kB)
signature.asc (197.00 B)
Digital signature
Download all attachments

2009-01-29 07:38:12

by Takashi Iwai

[permalink] [raw]
Subject: Re: [PATCH] ALSA: Don't cold reset AC97 codecs in some ICH chipsets

At Wed, 28 Jan 2009 13:52:59 -0200,
Thadeu Lima de Souza Cascardo wrote:
>
> On Wed, Jan 28, 2009 at 04:20:12PM +0100, Takashi Iwai wrote:
> > At Wed, 28 Jan 2009 12:40:42 -0200,
> > Thadeu Lima de Souza Cascardo wrote:
> > >
> > > Check in a quirk list if it should do cold reset when AC97 power saving
> > > is enabled. Some devices do not resume properly when cold reset,
> > > although power saving works OK.
> > >
> > > Signed-off-by: Thadeu Lima de Souza Cascardo <[email protected]>
> >
> > Thanks, applied now.
> >
> > ... and soon I found a build error when CONFIG_SND_AC97_POWERSAVE=n.
> > Fixed, too :)
>
>
> Sorry for this one. I've cleaned the modules and built them again with a
> changed config. Must have done something wrong in the build. Thanks for
> the fix.
>
> Regarding the warning fix in 92aab0a0, it is related to this commit:
> 248c982a, which was proposed by you during our previous discussion, and
> didn't really fix my problem.

I can't find these commit ids. Which tree are you referring to?


thanks,

Takashi

> I've been watching your tree ever since and this patch has been in your
> master branch since then, perhaps awaiting some conclusion about this
> issue.
>
> Do you think it solves any problems for other device models? In my case,
> if the cold reset was done, this would simply not work.
>
> Looking closer to the patch now, I see a point in keeping it, which may
> be the reason you did so. It will make the resume faster in those cases
> the init_bits are different from what the driver though would be there.
>
> In this case, I think the log message should be more clear about that,
> since it seems to indicate that the commit makes the driver wait for
> more codecs (all codec slots) than before the commit.
>
> Regards,
> Cascardo.