예제 #1
0
void
cs4280_set_dac_rate(struct cs4280_softc *sc, int rate)
{
	/*
	 * playback rate may range from 8000Hz to 48000Hz
	 *
	 * play_phase_increment = floor(rate*65536*1024/48000)
	 * px = round(rate*65536*1024 - play_phase_incremnt*48000)
	 * py=floor(px/200)
	 * play_sample_rate_correction = px - 200*py
	 *
	 * play_phase_increment is a 32bit signed quantity.
	 * play_sample_rate_correction is a 16bit signed quantity.
	 */
	int32_t ppi;
	int16_t psrc;
	u_int32_t px, py;
	
	if (rate < 8000)
		rate = 8000;
	if (rate > 48000)
		rate = 48000;
	px = rate << 16;
	ppi = px/48000;
	px -= ppi*48000;
	ppi <<= 10;
	px  <<= 10;
	py  = px / 48000;
	ppi += py;
	px -= py*48000;
	py  = px/200;
	px -= py*200;
	psrc = px;
#if 0
	/* what manual says */
	px = BA1READ4(sc, CS4280_PSRC) & ~PSRC_MASK;
	BA1WRITE4(sc, CS4280_PSRC,
			  ( ((psrc<<16) & PSRC_MASK) | px ));
#else	
	/* suggested by cs461x.c (ALSA driver) */
	BA1WRITE4(sc, CS4280_PSRC, CS4280_MK_PSRC(psrc,py));
#endif
	BA1WRITE4(sc, CS4280_PPI, ppi);
}
예제 #2
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;
		}
예제 #3
0
void
cs4280_set_adc_rate(struct cs4280_softc *sc, int rate)
{
	/* calculate capture rate:
	 *
	 * capture_coefficient_increment = -round(rate*128*65536/48000;
	 * capture_phase_increment	 = floor(48000*65536*1024/rate);
	 * cx = round(48000*65536*1024 - capture_phase_increment*rate);
	 * cy = floor(cx/200);
	 * capture_sample_rate_correction = cx - 200*cy;
	 * capture_delay = ceil(24*48000/rate);
	 * capture_num_triplets = floor(65536*rate/24000);
	 * capture_group_length = 24000/GCD(rate, 24000);
	 * where GCD means "Greatest Common Divisor".
	 *
	 * capture_coefficient_increment, capture_phase_increment and
	 * capture_num_triplets are 32-bit signed quantities.
	 * capture_sample_rate_correction and capture_group_length are
	 * 16-bit signed quantities.
	 * capture_delay is a 14-bit unsigned quantity.
	 */
	u_int32_t cci,cpi,cnt,cx,cy,  tmp1;
	u_int16_t csrc, cgl, cdlay;
	
	/* XXX
	 * Even though, embedded_audio_spec says capture rate range 11025 to
	 * 48000, dhwiface.cpp says,
	 *
	 * "We can only decimate by up to a factor of 1/9th the hardware rate.
	 *  Return an error if an attempt is made to stray outside that limit."
	 *
	 * so assume range as 48000/9 to 48000
	 */ 

	if (rate < 8000)
		rate = 8000;
	if (rate > 48000)
		rate = 48000;

	cx = rate << 16;
	cci = cx / 48000;
	cx -= cci * 48000;
	cx <<= 7;
	cci <<= 7;
	cci += cx / 48000;
	cci = - cci;

	cx = 48000 << 16;
	cpi = cx / rate;
	cx -= cpi * rate;
	cx <<= 10;
	cpi <<= 10;
	cy = cx / rate;
	cpi += cy;
	cx -= cy * rate;

	cy   = cx / 200;
	csrc = cx - 200*cy;

	cdlay = ((48000 * 24) + rate - 1) / rate;
#if 0
	cdlay &= 0x3fff; /* make sure cdlay is 14-bit */
#endif

	cnt  = rate << 16;
	cnt  /= 24000;

	cgl = 1;
	for (tmp1 = 2; tmp1 <= 64; tmp1 *= 2) {
		if (((rate / tmp1) * tmp1) != rate)
			cgl *= 2;
	}
	if (((rate / 3) * 3) != rate)
		cgl *= 3;
	for (tmp1 = 5; tmp1 <= 125; tmp1 *= 5) {
		if (((rate / tmp1) * tmp1) != rate) 
			cgl *= 5;
	}
#if 0
	/* XXX what manual says */
	tmp1 = BA1READ4(sc, CS4280_CSRC) & ~CSRC_MASK;
	tmp1 |= csrc<<16;
	BA1WRITE4(sc, CS4280_CSRC, tmp1);
#else
	/* suggested by cs461x.c (ALSA driver) */
	BA1WRITE4(sc, CS4280_CSRC, CS4280_MK_CSRC(csrc, cy));
#endif

#if 0
	/* I am confused.  The sample rate calculation section says
	 * cci *is* 32-bit signed quantity but in the parameter description
	 * section, CCI only assigned 16bit.
	 * I believe size of the variable.
	 */
	tmp1 = BA1READ4(sc, CS4280_CCI) & ~CCI_MASK;
	tmp1 |= cci<<16;
	BA1WRITE4(sc, CS4280_CCI, tmp1);
#else
	BA1WRITE4(sc, CS4280_CCI, cci);
#endif

	tmp1 = BA1READ4(sc, CS4280_CD) & ~CD_MASK;
	tmp1 |= cdlay <<18;
	BA1WRITE4(sc, CS4280_CD, tmp1);
	
	BA1WRITE4(sc, CS4280_CPI, cpi);
	
	tmp1 = BA1READ4(sc, CS4280_CGL) & ~CGL_MASK;
	tmp1 |= cgl;
	BA1WRITE4(sc, CS4280_CGL, tmp1);

	BA1WRITE4(sc, CS4280_CNT, cnt);
	
	tmp1 = BA1READ4(sc, CS4280_CGC) & ~CGC_MASK;
	tmp1 |= cgl;
	BA1WRITE4(sc, CS4280_CGC, tmp1);
}