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 void snd_via82xx_codec_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val) { struct via82xx_modem *chip = ac97->private_data; unsigned int xval; if(reg == AC97_GPIO_STATUS) { outl(val, VIAREG(chip, GPI_STATUS)); return; } xval = !ac97->num ? VIA_REG_AC97_CODEC_ID_PRIMARY : VIA_REG_AC97_CODEC_ID_SECONDARY; xval <<= VIA_REG_AC97_CODEC_ID_SHIFT; xval |= reg << VIA_REG_AC97_CMD_SHIFT; xval |= val << VIA_REG_AC97_DATA_SHIFT; snd_via82xx_codec_xwrite(chip, xval); snd_via82xx_codec_ready(chip, ac97->num); }
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; }