int cs428x_read_codec(void *addr, u_int8_t ac97_addr, u_int16_t *ac97_data) { struct cs428x_softc *sc; u_int32_t acctl; int n; sc = addr; DPRINTFN(5,("read_codec: add=0x%02x ", ac97_addr)); /* * Make sure that there is not data sitting around from a preivous * uncompleted access. */ BA0READ4(sc, CS428X_ACSDA); /* Set up AC97 control registers. */ BA0WRITE4(sc, CS428X_ACCAD, ac97_addr); BA0WRITE4(sc, CS428X_ACCDA, 0); acctl = ACCTL_ESYN | ACCTL_VFRM | ACCTL_CRW | ACCTL_DCV; if (sc->type == TYPE_CS4280) acctl |= ACCTL_RSTN; BA0WRITE4(sc, CS428X_ACCTL, acctl); if (cs428x_src_wait(sc) < 0) { printf("%s: AC97 read prob. (DCV!=0) for add=0x%0x\n", sc->sc_dev.dv_xname, ac97_addr); return 1; } /* wait for valid status bit is active */ n = 0; while ((BA0READ4(sc, CS428X_ACSTS) & ACSTS_VSTS) == 0) { delay(1); while (++n > 1000) { printf("%s: AC97 read fail (VSTS==0) for add=0x%0x\n", sc->sc_dev.dv_xname, ac97_addr); return 1; } } *ac97_data = BA0READ4(sc, CS428X_ACSDA); DPRINTFN(5,("data=0x%04x\n", *ac97_data)); return 0; }
int cs4280_write_codec(void *sc_, u_int8_t add, u_int16_t data) { struct cs4280_softc *sc = sc_; DPRINTFN(5,("write_codec: add=0x%02x data=0x%04x\n", add, data)); BA0WRITE4(sc, CS4280_ACCAD, add); BA0WRITE4(sc, CS4280_ACCDA, data); BA0WRITE4(sc, CS4280_ACCTL, ACCTL_RSTN | ACCTL_ESYN | ACCTL_VFRM | ACCTL_DCV ); if (cs4280_src_wait(sc) < 0) { printf("%s: AC97 write fail (DCV!=0) for add=0x%02x data=" "0x%04x\n", sc->sc_dev.dv_xname, add, data); return (1); } return (0); }
int cs4280_read_codec(void *sc_, u_int8_t add, u_int16_t *data) { struct cs4280_softc *sc = sc_; int n; DPRINTFN(5,("read_codec: add=0x%02x ", add)); /* * Make sure that there is not data sitting around from a preivous * uncompleted access. */ BA0READ4(sc, CS4280_ACSDA); /* Set up AC97 control registers. */ BA0WRITE4(sc, CS4280_ACCAD, add); BA0WRITE4(sc, CS4280_ACCDA, 0); BA0WRITE4(sc, CS4280_ACCTL, ACCTL_RSTN | ACCTL_ESYN | ACCTL_VFRM | ACCTL_CRW | ACCTL_DCV ); if (cs4280_src_wait(sc) < 0) { printf("%s: AC97 read prob. (DCV!=0) for add=0x%02x\n", sc->sc_dev.dv_xname, add); return (1); } /* wait for valid status bit is active */ n = 0; while (!(BA0READ4(sc, CS4280_ACSTS) & ACSTS_VSTS)) { delay(1); while (++n > 1000) { printf("%s: AC97 read fail (VSTS==0) for add=0x%02x\n", sc->sc_dev.dv_xname, add); return (1); } } *data = BA0READ4(sc, CS4280_ACSDA); DPRINTFN(5,("data=0x%04x\n", *data)); return (0); }
int cs428x_write_codec(void *addr, u_int8_t ac97_addr, u_int16_t ac97_data) { struct cs428x_softc *sc; u_int32_t acctl; sc = addr; DPRINTFN(5,("write_codec: add=0x%02x data=0x%04x\n", ac97_addr, ac97_data)); BA0WRITE4(sc, CS428X_ACCAD, ac97_addr); BA0WRITE4(sc, CS428X_ACCDA, ac97_data); acctl = ACCTL_ESYN | ACCTL_VFRM | ACCTL_DCV; if (sc->type == TYPE_CS4280) acctl |= ACCTL_RSTN; BA0WRITE4(sc, CS428X_ACCTL, acctl); if (cs428x_src_wait(sc) < 0) { printf("%s: AC97 write fail (DCV!=0) for add=0x%02x data=" "0x%04x\n", sc->sc_dev.dv_xname, ac97_addr, ac97_data); return 1; } return 0; }
/* Interrupt handling function */ static int cs4280_intr(void *p) { /* * XXX * * Since CS4280 has only 4kB DMA buffer and * interrupt occurs every 2kB block, I create dummy buffer * which returns to audio driver and actual DMA buffer * using in DMA transfer. * * * ring buffer in audio.c is pointed by BUFADDR * <------ ring buffer size == 64kB ------> * <-----> blksize == 2048*(sc->sc_[pr]count) kB * |= = = =|= = = =|= = = =|= = = =|= = = =| * | | | | | | <- call audio_intp every * sc->sc_[pr]_count time. * * actual DMA buffer is pointed by KERNADDR * <-> DMA buffer size = 4kB * |= =| * * */ struct cs428x_softc *sc; uint32_t intr, mem; char * empty_dma; int handled; sc = p; handled = 0; mutex_spin_enter(&sc->sc_intr_lock); /* grab interrupt register then clear it */ intr = BA0READ4(sc, CS4280_HISR); BA0WRITE4(sc, CS4280_HICR, HICR_CHGM | HICR_IEV); /* not for us ? */ if ((intr & HISR_INTENA) == 0) { mutex_spin_exit(&sc->sc_intr_lock); return 0; } /* Playback Interrupt */ if (intr & HISR_PINT) { handled = 1; mem = BA1READ4(sc, CS4280_PFIE); BA1WRITE4(sc, CS4280_PFIE, (mem & ~PFIE_PI_MASK) | PFIE_PI_DISABLE); if (sc->sc_prun) { if ((sc->sc_pi%sc->sc_pcount) == 0) sc->sc_pintr(sc->sc_parg); /* copy buffer */ ++sc->sc_pi; empty_dma = sc->sc_pdma->addr; if (sc->sc_pi&1) empty_dma += sc->hw_blocksize; memcpy(empty_dma, sc->sc_pn, sc->hw_blocksize); sc->sc_pn += sc->hw_blocksize; if (sc->sc_pn >= sc->sc_pe) sc->sc_pn = sc->sc_ps; } else { aprint_error_dev(sc->sc_dev, "unexpected play intr\n"); } BA1WRITE4(sc, CS4280_PFIE, mem); } /* Capture Interrupt */ if (intr & HISR_CINT) { int i; int16_t rdata; handled = 1; mem = BA1READ4(sc, CS4280_CIE); BA1WRITE4(sc, CS4280_CIE, (mem & ~CIE_CI_MASK) | CIE_CI_DISABLE); if (sc->sc_rrun) { ++sc->sc_ri; empty_dma = sc->sc_rdma->addr; if ((sc->sc_ri&1) == 0) empty_dma += sc->hw_blocksize; /* * XXX * I think this audio data conversion should be * happend in upper layer, but I put this here * since there is no conversion function available. */ switch(sc->sc_rparam) { case CF_16BIT_STEREO: /* just copy it */ memcpy(sc->sc_rn, empty_dma, sc->hw_blocksize); sc->sc_rn += sc->hw_blocksize; break; case CF_16BIT_MONO: for (i = 0; i < 512; i++) { rdata = *((int16_t *)empty_dma)>>1; empty_dma += 2; rdata += *((int16_t *)empty_dma)>>1; empty_dma += 2; *((int16_t *)sc->sc_rn) = rdata; sc->sc_rn += 2; } break; case CF_8BIT_STEREO: for (i = 0; i < 512; i++) { rdata = *((int16_t*)empty_dma); empty_dma += 2; *sc->sc_rn++ = rdata >> 8; rdata = *((int16_t*)empty_dma); empty_dma += 2; *sc->sc_rn++ = rdata >> 8; } break; case CF_8BIT_MONO: for (i = 0; i < 512; i++) { rdata = *((int16_t*)empty_dma) >>1; empty_dma += 2; rdata += *((int16_t*)empty_dma) >>1; empty_dma += 2; *sc->sc_rn++ = rdata >>8; } break; default: /* Should not reach here */ aprint_error_dev(sc->sc_dev, "unknown sc->sc_rparam: %d\n", sc->sc_rparam); } if (sc->sc_rn >= sc->sc_re) sc->sc_rn = sc->sc_rs; }