/*
* access to AC97 codec via normal i/o (for ICH and SIS7012)
*/
+
+/* return the GLOB_STA bit for the corresponding codec */
+static unsigned int get_ich_codec_bit(intel8x0_t *chip, unsigned int codec)
+{
+ static unsigned int codec_bit[3] = {
+ ICH_PCR, ICH_SCR, ICH_TCR
+ };
+ snd_assert(codec < 3, return ICH_PCR);
+ if (chip->device_type == DEVICE_INTEL_ICH4)
+ codec = chip->ac97_sdin[codec];
+ return codec_bit[codec];
+}
+
static int snd_intel8x0_codec_semaphore(intel8x0_t *chip, unsigned int codec)
{
int time;
/* so we check any */
codec = ICH_PCR | ICH_SCR | ICH_TCR;
} else {
- if (chip->device_type == DEVICE_INTEL_ICH4) {
- switch (chip->ac97_sdin[codec]) {
- case 0: codec = ICH_PCR; break;
- case 1: codec = ICH_SCR; break;
- case 2: codec = ICH_TCR; break;
- }
- } else {
- switch (codec) {
- case 0: codec = ICH_PCR; break;
- case 1: codec = ICH_SCR; break;
- case 2: codec = ICH_TCR; break;
- }
- }
+ codec = get_ich_codec_bit(chip, codec);
}
/* codec ready ? */
}
}
ac97.pci = chip->pci;
- if ((err = snd_ac97_mixer(chip->card, &ac97, &x97)) < 0)
+ if ((err = snd_ac97_mixer(chip->card, &ac97, &x97)) < 0) {
+ /* clear the cold-reset bit for the next chance */
+ if (chip->device_type != DEVICE_ALI)
+ iputdword(chip, ICHREG(GLOB_CNT), igetdword(chip, ICHREG(GLOB_CNT)) & ~ICH_AC97COLD);
return err;
+ }
chip->ac97[0] = x97;
+ /* tune up the primary codec */
snd_ac97_tune_hardware(chip->ac97[0], ac97_quirks);
/* the following three entries are common among all devices */
chip->ichd[ICHD_PCMOUT].ac97 = x97;
schedule_timeout(1);\
} while (0)
-static int snd_intel8x0_ich_chip_init(intel8x0_t *chip)
+static int snd_intel8x0_ich_chip_init(intel8x0_t *chip, int probing)
{
unsigned long end_time;
unsigned int cnt, status, nstatus;
return -EIO;
__ok:
- /* wait for any codec ready status.
- * Once it becomes ready it should remain ready
- * as long as we do not disable the ac97 link.
- */
- end_time = jiffies + HZ;
- do {
- status = igetdword(chip, ICHREG(GLOB_STA)) & (ICH_PCR | ICH_SCR | ICH_TCR);
- if (status)
- goto __ok1;
- do_delay(chip);
- } while (time_after_eq(end_time, jiffies));
- snd_printk(KERN_ERR "codec_ready: codec is not ready [0x%x]\n", igetdword(chip, ICHREG(GLOB_STA)));
- return -EIO;
-
- __ok1:
- if (status == (ICH_PCR | ICH_SCR | ICH_TCR))
- goto __ok3;
- /* wait for other codecs ready status. No secondary codecs? , ok */
- end_time = jiffies + HZ / 4;
- do {
- nstatus = igetdword(chip, ICHREG(GLOB_STA)) & (ICH_PCR | ICH_SCR | ICH_TCR);
- if (nstatus != status) {
- status = nstatus;
- goto __ok2;
+ if (probing) {
+ /* wait for any codec ready status.
+ * Once it becomes ready it should remain ready
+ * as long as we do not disable the ac97 link.
+ */
+ end_time = jiffies + HZ;
+ do {
+ status = igetdword(chip, ICHREG(GLOB_STA)) & (ICH_PCR | ICH_SCR | ICH_TCR);
+ if (status)
+ break;
+ do_delay(chip);
+ } while (time_after_eq(end_time, jiffies));
+ if (! status) {
+ /* no codec is found */
+ snd_printk(KERN_ERR "codec_ready: codec is not ready [0x%x]\n", igetdword(chip, ICHREG(GLOB_STA)));
+ return -EIO;
}
- do_delay(chip);
- } while (time_after_eq(end_time, jiffies));
- __ok2:
- if (status == (ICH_PCR | ICH_SCR | ICH_TCR))
- goto __ok3;
- /* wait for other codecs ready status. No other secondary codecs? , ok */
- /* end_time is not initialized here */
- do {
- nstatus = igetdword(chip, ICHREG(GLOB_STA)) & (ICH_PCR | ICH_SCR | ICH_TCR);
- if (nstatus != status) {
- status = nstatus;
- goto __ok2;
+ if (chip->device_type == DEVICE_INTEL_ICH4)
+ /* ICH4 can have three codecs */
+ nstatus = ICH_PCR | ICH_SCR | ICH_TCR;
+ else
+ /* others up to two codecs */
+ nstatus = ICH_PCR | ICH_SCR;
+
+ /* wait for other codecs ready status. */
+ end_time = jiffies + HZ / 4;
+ while (status != nstatus && time_after_eq(end_time, jiffies)) {
+ do_delay(chip);
+ status |= igetdword(chip, ICHREG(GLOB_STA)) & nstatus;
}
- do_delay(chip);
- } while (time_after_eq(end_time, jiffies));
- __ok3:
+ } else {
+ /* resume phase */
+ int i;
+ status = 0;
+ for (i = 0; i < 3; i++)
+ if (chip->ac97[i])
+ status |= get_ich_codec_bit(chip, i);
+ /* wait until all the probed codecs are ready */
+ end_time = jiffies + HZ;
+ do {
+ nstatus = igetdword(chip, ICHREG(GLOB_STA)) & (ICH_PCR | ICH_SCR | ICH_TCR);
+ if (status == nstatus)
+ break;
+ do_delay(chip);
+ } while (time_after_eq(end_time, jiffies));
+ }
+
if (chip->device_type == DEVICE_SIS) {
/* unmute the output on SIS7012 */
iputword(chip, 0x4c, igetword(chip, 0x4c) | 1);
return 0;
}
-static int snd_intel8x0_ali_chip_init(intel8x0_t *chip)
+static int snd_intel8x0_ali_chip_init(intel8x0_t *chip, int probing)
{
u32 reg;
int i = 0;
do_delay(chip);
}
snd_printk(KERN_ERR "AC'97 reset failed.\n");
- return -EIO;
+ if (probing)
+ return -EIO;
__ok:
for (i = 0; i < HZ / 2; i++) {
return 0;
}
-static int snd_intel8x0_chip_init(intel8x0_t *chip)
+static int snd_intel8x0_chip_init(intel8x0_t *chip, int probing)
{
unsigned int i;
int err;
if (chip->device_type != DEVICE_ALI) {
- if ((err = snd_intel8x0_ich_chip_init(chip)) < 0)
+ if ((err = snd_intel8x0_ich_chip_init(chip, probing)) < 0)
return err;
iagetword(chip, 0); /* clear semaphore flag */
} else {
- if ((err = snd_intel8x0_ali_chip_init(chip)) < 0)
+ if ((err = snd_intel8x0_ali_chip_init(chip, probing)) < 0)
return err;
}
pci_enable_device(chip->pci);
pci_set_master(chip->pci);
- snd_intel8x0_chip_init(chip);
+ snd_intel8x0_chip_init(chip, 0);
for (i = 0; i < 3; i++)
if (chip->ac97[i])
snd_ac97_resume(chip->ac97[i]);
chip->int_sta_reg = device_type == DEVICE_ALI ? ICH_REG_ALI_INTERRUPTSR : ICH_REG_GLOB_STA;
chip->int_sta_mask = int_sta_masks;
- if ((err = snd_intel8x0_chip_init(chip)) < 0) {
+ if ((err = snd_intel8x0_chip_init(chip, 1)) < 0) {
snd_intel8x0_free(chip);
return err;
}