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/
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
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.
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.
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
--
Thanks, applied now.
.. and soon I found a build error when CONFIG_SND_AC97_POWERSAVE=n.
Fixed, too :)
Takashi
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.
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.