static unsigned short snd_via82xx_codec_read(struct snd_ac97 *ac97, unsigned short reg) { struct via82xx_modem *chip = ac97->private_data; unsigned int xval, val = 0xffff; int again = 0; xval = ac97->num << VIA_REG_AC97_CODEC_ID_SHIFT; xval |= ac97->num ? VIA_REG_AC97_SECONDARY_VALID : VIA_REG_AC97_PRIMARY_VALID; xval |= VIA_REG_AC97_READ; xval |= (reg & 0x7f) << VIA_REG_AC97_CMD_SHIFT; while (1) { if (again++ > 3) { snd_printk(KERN_ERR "codec_read: codec %i is not valid [0x%x]\n", ac97->num, snd_via82xx_codec_xread(chip)); return 0xffff; } snd_via82xx_codec_xwrite(chip, xval); udelay (20); if (snd_via82xx_codec_valid(chip, ac97->num) >= 0) { udelay(25); val = snd_via82xx_codec_xread(chip); break; } } return val & 0xffff; }
static int snd_via82xx_codec_ready(struct via82xx_modem *chip, int secondary) { unsigned int timeout = 1000; /* 1ms */ unsigned int val; while (timeout-- > 0) { udelay(1); if (!((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY)) return val & 0xffff; } snd_printk(KERN_ERR "codec_ready: codec %i is not ready [0x%x]\n", secondary, snd_via82xx_codec_xread(chip)); return -EIO; }
static int snd_via82xx_codec_valid(struct via82xx_modem *chip, int secondary) { unsigned int timeout = 1000; /* 1ms */ unsigned int val, val1; unsigned int stat = !secondary ? VIA_REG_AC97_PRIMARY_VALID : VIA_REG_AC97_SECONDARY_VALID; while (timeout-- > 0) { val = snd_via82xx_codec_xread(chip); val1 = val & (VIA_REG_AC97_BUSY | stat); if (val1 == stat) return val & 0xffff; udelay(1); } return -EIO; }
static int snd_via82xx_chip_init(struct via82xx_modem *chip) { unsigned int val; unsigned long end_time; unsigned char pval; pci_read_config_byte(chip->pci, VIA_MC97_CTRL, &pval); if((pval & VIA_MC97_CTRL_INIT) != VIA_MC97_CTRL_INIT) { pci_write_config_byte(chip->pci, 0x44, pval|VIA_MC97_CTRL_INIT); udelay(100); } pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval); if (! (pval & VIA_ACLINK_C00_READY)) { /* codec not ready? */ /* deassert ACLink reset, force SYNC */ pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL, VIA_ACLINK_CTRL_ENABLE | VIA_ACLINK_CTRL_RESET | VIA_ACLINK_CTRL_SYNC); udelay(100); #if 1 /* FIXME: should we do full reset here for all chip models? */ pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL, 0x00); udelay(100); #else /* deassert ACLink reset, force SYNC (warm AC'97 reset) */ pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL, VIA_ACLINK_CTRL_RESET|VIA_ACLINK_CTRL_SYNC); udelay(2); #endif /* ACLink on, deassert ACLink reset, VSR, SGD data out */ pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL, VIA_ACLINK_CTRL_INIT); udelay(100); } pci_read_config_byte(chip->pci, VIA_ACLINK_CTRL, &pval); if ((pval & VIA_ACLINK_CTRL_INIT) != VIA_ACLINK_CTRL_INIT) { /* ACLink on, deassert ACLink reset, VSR, SGD data out */ pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL, VIA_ACLINK_CTRL_INIT); udelay(100); } /* wait until codec ready */ end_time = jiffies + msecs_to_jiffies(750); do { pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval); if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */ break; schedule_timeout_uninterruptible(1); } while (time_before(jiffies, end_time)); if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) snd_printk(KERN_ERR "AC'97 codec is not ready [0x%x]\n", val); snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ | VIA_REG_AC97_SECONDARY_VALID | (VIA_REG_AC97_CODEC_ID_SECONDARY << VIA_REG_AC97_CODEC_ID_SHIFT)); end_time = jiffies + msecs_to_jiffies(750); snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ | VIA_REG_AC97_SECONDARY_VALID | (VIA_REG_AC97_CODEC_ID_SECONDARY << VIA_REG_AC97_CODEC_ID_SHIFT)); do { if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_SECONDARY_VALID) { chip->ac97_secondary = 1; goto __ac97_ok2; } schedule_timeout_uninterruptible(1); } while (time_before(jiffies, end_time)); /* This is ok, the most of motherboards have only one codec */ __ac97_ok2: /* route FM trap to IRQ, disable FM trap */ // pci_write_config_byte(chip->pci, VIA_FM_NMI_CTRL, 0); /* disable all GPI interrupts */ outl(0, VIAREG(chip, GPI_INTR)); return 0; }
static int snd_via82xx_chip_init(struct via82xx_modem *chip) { unsigned int val; unsigned long end_time; unsigned char pval; pci_read_config_byte(chip->pci, VIA_MC97_CTRL, &pval); if((pval & VIA_MC97_CTRL_INIT) != VIA_MC97_CTRL_INIT) { pci_write_config_byte(chip->pci, 0x44, pval|VIA_MC97_CTRL_INIT); udelay(100); } pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval); if (! (pval & VIA_ACLINK_C00_READY)) { /* */ /* */ pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL, VIA_ACLINK_CTRL_ENABLE | VIA_ACLINK_CTRL_RESET | VIA_ACLINK_CTRL_SYNC); udelay(100); #if 1 /* */ pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL, 0x00); udelay(100); #else /* */ pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL, VIA_ACLINK_CTRL_RESET|VIA_ACLINK_CTRL_SYNC); udelay(2); #endif /* */ pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL, VIA_ACLINK_CTRL_INIT); udelay(100); } pci_read_config_byte(chip->pci, VIA_ACLINK_CTRL, &pval); if ((pval & VIA_ACLINK_CTRL_INIT) != VIA_ACLINK_CTRL_INIT) { /* */ pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL, VIA_ACLINK_CTRL_INIT); udelay(100); } /* */ end_time = jiffies + msecs_to_jiffies(750); do { pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval); if (pval & VIA_ACLINK_C00_READY) /* */ break; schedule_timeout_uninterruptible(1); } while (time_before(jiffies, end_time)); if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) snd_printk(KERN_ERR "AC'97 codec is not ready [0x%x]\n", val); snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ | VIA_REG_AC97_SECONDARY_VALID | (VIA_REG_AC97_CODEC_ID_SECONDARY << VIA_REG_AC97_CODEC_ID_SHIFT)); end_time = jiffies + msecs_to_jiffies(750); snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ | VIA_REG_AC97_SECONDARY_VALID | (VIA_REG_AC97_CODEC_ID_SECONDARY << VIA_REG_AC97_CODEC_ID_SHIFT)); do { if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_SECONDARY_VALID) { chip->ac97_secondary = 1; goto __ac97_ok2; } schedule_timeout_uninterruptible(1); } while (time_before(jiffies, end_time)); /* */ __ac97_ok2: /* */ // /* */ outl(0, VIAREG(chip, GPI_INTR)); return 0; }