Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
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);
}
Ejemplo n.º 3
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);
}
Ejemplo n.º 4
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;
}
Ejemplo n.º 5
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;
		}