int yds_write_codec(void *sc_, u_int8_t reg, u_int16_t data) { struct yds_codec_softc *sc = sc_; YWRITE2(sc->sc, AC97_CMD_ADDR, AC97_CMD_WRITE | AC97_ID(sc->id) | reg); YWRITE2(sc->sc, AC97_CMD_DATA, data); if (yds_ready_codec(sc)) { printf("%s: yds_write_codec timeout\n", sc->sc->sc_dev.dv_xname); return EIO; } return 0; }
static int yds_write_codec(void *sc_, uint8_t reg, uint16_t data) { struct yds_codec_softc *sc; sc = sc_; YWRITE2(sc->sc, AC97_CMD_ADDR, AC97_CMD_WRITE | AC97_ID(sc->id) | reg); YWRITE2(sc->sc, AC97_CMD_DATA, data); if (yds_ready_codec(sc)) { aprint_error_dev(sc->sc->sc_dev, "yds_write_codec timeout\n"); return EIO; } return 0; }
int yds_read_codec(void *sc_, u_int8_t reg, u_int16_t *data) { struct yds_codec_softc *sc = sc_; YWRITE2(sc->sc, AC97_CMD_ADDR, AC97_CMD_READ | AC97_ID(sc->id) | reg); if (yds_ready_codec(sc)) { printf("%s: yds_read_codec timeout\n", sc->sc->sc_dev.dv_xname); return EIO; } if (PCI_PRODUCT(sc->sc->sc_id) == PCI_PRODUCT_YAMAHA_YMF744 && sc->sc->sc_revision < 2) { int i; for (i = 0; i < 600; i++) YREAD2(sc->sc, sc->status_data); } *data = YREAD2(sc->sc, sc->status_data); return 0; }
static int yds_read_codec(void *sc_, uint8_t reg, uint16_t *data) { struct yds_codec_softc *sc; sc = sc_; YWRITE2(sc->sc, AC97_CMD_ADDR, AC97_CMD_READ | AC97_ID(sc->id) | reg); if (yds_ready_codec(sc)) { aprint_error_dev(sc->sc->sc_dev, "yds_read_codec timeout\n"); return EIO; } if (PCI_PRODUCT(sc->sc->sc_id) == PCI_PRODUCT_YAMAHA_YMF744B && sc->sc->sc_revision < 2) { int i; for (i=0; i<600; i++) (void)YREAD2(sc->sc, sc->status_data); } *data = YREAD2(sc->sc, sc->status_data); return 0; }
static void yds_attach(device_t parent, device_t self, void *aux) { struct yds_softc *sc; struct pci_attach_args *pa; pci_chipset_tag_t pc; char const *intrstr; pci_intr_handle_t ih; pcireg_t reg; struct yds_codec_softc *codec; int i, r, to; int revision; int ac97_id2; char intrbuf[PCI_INTRSTR_LEN]; sc = device_private(self); sc->sc_dev = self; pa = (struct pci_attach_args *)aux; pc = pa->pa_pc; revision = PCI_REVISION(pa->pa_class); pci_aprint_devinfo(pa, NULL); /* Map register to memory */ if (pci_mapreg_map(pa, YDS_PCI_MBA, PCI_MAPREG_TYPE_MEM, 0, &sc->memt, &sc->memh, NULL, NULL)) { aprint_error_dev(self, "can't map memory space\n"); return; } /* Map and establish the interrupt. */ if (pci_intr_map(pa, &ih)) { aprint_error_dev(self, "couldn't map interrupt\n"); return; } mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_AUDIO); /* XXX IPL_NONE? */ mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_AUDIO); intrstr = pci_intr_string(pc, ih, intrbuf, sizeof(intrbuf)); sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, yds_intr, sc); if (sc->sc_ih == NULL) { aprint_error_dev(self, "couldn't establish interrupt"); if (intrstr != NULL) aprint_error(" at %s", intrstr); aprint_error("\n"); mutex_destroy(&sc->sc_lock); mutex_destroy(&sc->sc_intr_lock); return; } aprint_normal_dev(self, "interrupting at %s\n", intrstr); sc->sc_dmatag = pa->pa_dmat; sc->sc_pc = pc; sc->sc_pcitag = pa->pa_tag; sc->sc_id = pa->pa_id; sc->sc_revision = revision; sc->sc_flags = yds_get_dstype(sc->sc_id); #ifdef AUDIO_DEBUG if (ydsdebug) { char bits[80]; snprintb(bits, sizeof(bits), YDS_CAP_BITS, sc->sc_flags); printf("%s: chip has %s\n", device_xname(self), bits); } #endif /* Disable legacy mode */ reg = pci_conf_read(pc, pa->pa_tag, YDS_PCI_LEGACY); pci_conf_write(pc, pa->pa_tag, YDS_PCI_LEGACY, reg & YDS_PCI_LEGACY_LAD); /* Enable the device. */ reg = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); reg |= (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE); pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, reg); reg = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); /* Mute all volumes */ for (i = 0x80; i < 0xc0; i += 2) YWRITE2(sc, i, 0); /* Initialize the device */ if (yds_init(sc)) { aprint_error_dev(self, "initialize failed\n"); mutex_destroy(&sc->sc_lock); mutex_destroy(&sc->sc_intr_lock); return; } /* * Detect primary/secondary AC97 * YMF754 Hardware Specification Rev 1.01 page 24 */ reg = pci_conf_read(pc, pa->pa_tag, YDS_PCI_DSCTRL); pci_conf_write(pc, pa->pa_tag, YDS_PCI_DSCTRL, reg & ~YDS_DSCTRL_CRST); delay(400000); /* Needed for 740C. */ /* Primary */ for (to = 0; to < AC97_TIMEOUT; to++) { if ((YREAD2(sc, AC97_STAT_ADDR1) & AC97_BUSY) == 0) break; delay(1); } if (to == AC97_TIMEOUT) { aprint_error_dev(self, "no AC97 available\n"); mutex_destroy(&sc->sc_lock); mutex_destroy(&sc->sc_intr_lock); return; } /* Secondary */ /* Secondary AC97 is used for 4ch audio. Currently unused. */ ac97_id2 = -1; if ((YREAD2(sc, YDS_ACTIVITY) & YDS_ACTIVITY_DOCKA) == 0) goto detected; #if 0 /* reset secondary... */ YWRITE2(sc, YDS_GPIO_OCTRL, YREAD2(sc, YDS_GPIO_OCTRL) & ~YDS_GPIO_GPO2); YWRITE2(sc, YDS_GPIO_FUNCE, (YREAD2(sc, YDS_GPIO_FUNCE)&(~YDS_GPIO_GPC2))|YDS_GPIO_GPE2); #endif for (to = 0; to < AC97_TIMEOUT; to++) { if ((YREAD2(sc, AC97_STAT_ADDR2) & AC97_BUSY) == 0) break; delay(1); } if (to < AC97_TIMEOUT) { /* detect id */ for (ac97_id2 = 1; ac97_id2 < 4; ac97_id2++) { YWRITE2(sc, AC97_CMD_ADDR, AC97_CMD_READ | AC97_ID(ac97_id2) | 0x28); for (to = 0; to < AC97_TIMEOUT; to++) { if ((YREAD2(sc, AC97_STAT_ADDR2) & AC97_BUSY) == 0) goto detected; delay(1); } } if (ac97_id2 == 4) ac97_id2 = -1; detected: ; } pci_conf_write(pc, pa->pa_tag, YDS_PCI_DSCTRL, reg | YDS_DSCTRL_CRST); delay (20); pci_conf_write(pc, pa->pa_tag, YDS_PCI_DSCTRL, reg & ~YDS_DSCTRL_CRST); delay (400000); for (to = 0; to < AC97_TIMEOUT; to++) { if ((YREAD2(sc, AC97_STAT_ADDR1) & AC97_BUSY) == 0) break; delay(1); } /* * Attach ac97 codec */ for (i = 0; i < 2; i++) { static struct { int data; int addr; } statregs[] = { {AC97_STAT_DATA1, AC97_STAT_ADDR1}, {AC97_STAT_DATA2, AC97_STAT_ADDR2}, }; if (i == 1 && ac97_id2 == -1) break; /* secondary ac97 not available */ codec = &sc->sc_codec[i]; codec->sc = sc; codec->id = i == 1 ? ac97_id2 : 0; codec->status_data = statregs[i].data; codec->status_addr = statregs[i].addr; codec->host_if.arg = codec; codec->host_if.attach = yds_attach_codec; codec->host_if.read = yds_read_codec; codec->host_if.write = yds_write_codec; codec->host_if.reset = yds_reset_codec; r = ac97_attach(&codec->host_if, self, &sc->sc_lock); if (r != 0) { aprint_error_dev(self, "can't attach codec (error 0x%X)\n", r); mutex_destroy(&sc->sc_lock); mutex_destroy(&sc->sc_intr_lock); return; } } if (0 != auconv_create_encodings(yds_formats, YDS_NFORMATS, &sc->sc_encodings)) { mutex_destroy(&sc->sc_lock); mutex_destroy(&sc->sc_intr_lock); return; } audio_attach_mi(&yds_hw_if, sc, self); sc->sc_legacy_iot = pa->pa_iot; config_defer(self, yds_configure_legacy); if (!pmf_device_register(self, yds_suspend, yds_resume)) aprint_error_dev(self, "couldn't establish power handler\n"); }