Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

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

1 view
Skip to first unread message

Thadeu Lima de Souza Cascardo

unread,
Jan 28, 2009, 5:35:42 AM1/28/09
to ti...@suse.de, linux-...@vger.kernel.org, Thadeu Lima de Souza Cascardo
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 <casc...@holoscopio.com>
---
sound/pci/intel8x0.c | 60 ++++++++++++++++++++++++++++++++++++-------------
1 files changed, 44 insertions(+), 16 deletions(-)

diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index 19d3391..69b3ed8 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,50 @@ 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;
+}
#else
+#define snd_intel8x0_ich_chip_cold_reset(x) 0
+#endif
+
+static int snd_intel8x0_ich_chip_reset(struct intel8x0 *chip)
+{
+ 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;
+ 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_cold_reset(chip) < 0)
+ if ((err = snd_intel8x0_ich_chip_reset(chip)) < 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

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majo...@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

Takashi Iwai

unread,
Jan 28, 2009, 7:06:47 AM1/28/09
to Thadeu Lima de Souza Cascardo, linux-...@vger.kernel.org
At Wed, 28 Jan 2009 08:02:36 -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 <casc...@holoscopio.com>

Thanks for the patch.
We can go better further with this patch now :)

The logic is basically fine, but just a few comments...

> diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
> index 19d3391..69b3ed8 100644
> --- a/sound/pci/intel8x0.c
> +++ b/sound/pci/intel8x0.c

..


> +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;

I feel it isn't intuitive to return -EIO here.
It'd be more straightforward to call snd_intel8x0_ich_chip_reset()
from here?

if (snd_pci_quirk_lookup(chip->pci, ich_chip_reset_mode))
return snd_intl8x0_ich_chip_reset(chip);


> + if (snd_intel8x0_ich_chip_cold_reset(chip) < 0)
> + if ((err = snd_intel8x0_ich_chip_reset(chip)) < 0)
> + return err;

Please make the change checkpatch-clean.

Could you fix and repost?


thanks,

Takashi

Thadeu Lima de Souza Cascardo

unread,
Jan 28, 2009, 7:27:23 AM1/28/09
to Takashi Iwai, linux-...@vger.kernel.org
On Wed, Jan 28, 2009 at 01:06:20PM +0100, Takashi Iwai wrote:
> At Wed, 28 Jan 2009 08:02:36 -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 <casc...@holoscopio.com>
>
> Thanks for the patch.
> We can go better further with this patch now :)
>
> The logic is basically fine, but just a few comments...
>
> > diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
> > index 19d3391..69b3ed8 100644
> > --- a/sound/pci/intel8x0.c
> > +++ b/sound/pci/intel8x0.c
> ...

> > +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;
>
> I feel it isn't intuitive to return -EIO here.
> It'd be more straightforward to call snd_intel8x0_ich_chip_reset()
> from here?
>
> if (snd_pci_quirk_lookup(chip->pci, ich_chip_reset_mode))
> return snd_intl8x0_ich_chip_reset(chip);
>
>
> > + if (snd_intel8x0_ich_chip_cold_reset(chip) < 0)
> > + if ((err = snd_intel8x0_ich_chip_reset(chip)) < 0)
> > + return err;
>
> Please make the change checkpatch-clean.
>
> Could you fix and repost?

I did checkpatch it, but since this style is used in many places in the
intel8x0.c code, I thought I would leave it this way. Should I send a
cleanup patch too?

By the way, I have some very trivial comment typo patches lying around.
I will post them too.

>
>
> thanks,
>
> Takashi

Regards,
Cascardo.

signature.asc

Takashi Iwai

unread,
Jan 28, 2009, 8:02:25 AM1/28/09
to Thadeu Lima de Souza Cascardo, linux-...@vger.kernel.org
At Wed, 28 Jan 2009 10:27:30 -0200,

Just make your patch checkpatch-clean. The other parts don't have to
be changed in this case.

> By the way, I have some very trivial comment typo patches lying around.
> I will post them too.

That'll be fine.

Thadeu Lima de Souza Cascardo

unread,
Jan 28, 2009, 9:40:34 AM1/28/09
to ti...@suse.de, linux-...@vger.kernel.org, Thadeu Lima de Souza Cascardo
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 <casc...@holoscopio.com>

---
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

--

Takashi Iwai

unread,
Jan 28, 2009, 10:20:34 AM1/28/09
to Thadeu Lima de Souza Cascardo, linux-...@vger.kernel.org
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 <casc...@holoscopio.com>

Thanks, applied now.

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


Takashi

Thadeu Lima de Souza Cascardo

unread,
Jan 28, 2009, 10:52:50 AM1/28/09
to Takashi Iwai, linux-...@vger.kernel.org
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 <casc...@holoscopio.com>
>
> 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.

signature.asc

Takashi Iwai

unread,
Jan 29, 2009, 2:38:18 AM1/29/09
to Thadeu Lima de Souza Cascardo, linux-...@vger.kernel.org
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 <casc...@holoscopio.com>
> >
> > 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.

0 new messages