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); }
/* 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; }
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); }