void audio_setup_dma(void); void audio_enable_interrupts(void); void clock_failure_detect_setup(void); void mcasp_init(void) { audio_disable_interrupts(); ASSERT(mcasp->regs->REVID == 0x44300a02, "Perhaps your McASP is not turned on."); dma_regs->SHADOW[1].ECR = 0xFFFFFFFF; // clearing dma_regs->ER to check for any AXEVT signal later. TSK_sleep(10); // Follow section 2.4.1.2 carefully during initialization. // Step 1 mcasp->regs->GBLCTL = 0; mcasp->regs->PFUNC = 0; mcasp->regs->XINTCTL= 0; mcasp->regs->RINTCTL= 0; while (mcasp->regs->GBLCTL != 0); // Step 2: Configure the FIFO // 2.a: write fifo CSL_FINST(mcasp->fifo->WFIFOCTL, AFIFO_WFIFOCTL_WENA, DISABLED); CSL_FINST(mcasp->fifo->RFIFOCTL, AFIFO_RFIFOCTL_RENA, DISABLED); // 3.a: RMASK, RFMT, AFSRCTL, ACLKRCTL, AHCLKRCTL, RTDM, RINTCTL, RCLKCHK mcasp->regs->RMASK = 0xFFFFFFFF; // keep all 32 bits of data. // For sync transfer: // RSSZ * RMOD == XSSZ * XMOD // BOTH TX AND RX IN TDM // ACLKRCTL is irrelevant. // RCLK is an inverted version of XCLK // FSXM must match FSRM // FXWID Must match FRWID mcasp->regs->RFMT = CSL_FMKT( MCASP_RFMT_RDATDLY, 0BIT) | CSL_FMKT( MCASP_RFMT_RRVRS, MSBFIRST) | CSL_FMKT( MCASP_RFMT_RPAD, ZERO) | CSL_FMK ( MCASP_RFMT_RPBIT, 0) | CSL_FMKT( MCASP_RFMT_RSSZ, 32BITS) | CSL_FMKT( MCASP_RFMT_RBUSEL, VBUSP) | CSL_FMKT( MCASP_RFMT_RROT, NONE) ; mcasp->regs->AFSRCTL = CSL_FMK ( MCASP_AFSRCTL_RMOD, 8) | CSL_FMKT( MCASP_AFSRCTL_FRWID, BIT) | CSL_FMKT( MCASP_AFSRCTL_FSRM, EXTERNAL) | CSL_FMKT( MCASP_AFSRCTL_FSRP, RISINGEDGE); // ACLKRCTL should not be relavent to sync mode. but programming it // because I can't get the proper AXEVENT to happen. mcasp->regs->ACLKRCTL = CSL_FMKT(MCASP_ACLKRCTL_CLKRP , FALLINGEDGE ) | CSL_FMKT(MCASP_ACLKRCTL_CLKRM , INTERNAL) | CSL_FMK (MCASP_ACLKRCTL_CLKRDIV, 0 ) ; mcasp->regs->RTDM = 0x000000FF; // receive in all 8 time slots. mcasp->regs->RINTCTL = CSL_FMKT( MCASP_RINTCTL_RSTAFRM , DISABLE ) | CSL_FMKT( MCASP_RINTCTL_RDATA , DISABLE ) | CSL_FMKT( MCASP_RINTCTL_RLAST , DISABLE ) | CSL_FMKT( MCASP_RINTCTL_RDMAERR , ENABLE ) | CSL_FMKT( MCASP_RINTCTL_RCKFAIL , DISABLE ) | CSL_FMKT( MCASP_RINTCTL_RSYNCERR, ENABLE ) | CSL_FMKT( MCASP_RINTCTL_ROVRN , ENABLE ) ; mcasp->regs->RCLKCHK = ( 255 << CSL_MCASP_RCLKCHK_RMAX_SHIFT) | ( 0 << CSL_MCASP_RCLKCHK_RMIN_SHIFT) | ( 1 << CSL_MCASP_RCLKCHK_RPS_SHIFT); // // 3.b: Transmit registers: XMASK, XFMT, AFSXCTL, ACLKXCTL, AHCLKXCTL, XTDM, XINTCTL, XCLKCHK // mcasp->regs->XMASK = 0xFFFFFFFF; mcasp->regs->XFMT = CSL_FMKT( MCASP_XFMT_XDATDLY, 0BIT ) | CSL_FMKT( MCASP_XFMT_XRVRS , MSBFIRST ) | CSL_FMKT( MCASP_XFMT_XPAD , ZERO ) | CSL_FMK ( MCASP_XFMT_XPBIT , 0 ) | CSL_FMKT( MCASP_XFMT_XSSZ , 32BITS ) | CSL_FMKT( MCASP_XFMT_XBUSEL , VBUSP ) | CSL_FMKT( MCASP_XFMT_XROT , NONE ) ; mcasp->regs->AFSXCTL = CSL_FMK ( MCASP_AFSXCTL_XMOD, 8 ) | CSL_FMKT( MCASP_AFSXCTL_FXWID, BIT ) | CSL_FMKT( MCASP_AFSXCTL_FSXM , EXTERNAL ) | CSL_FMKT( MCASP_AFSXCTL_FSXP , RISINGEDGE) ; mcasp->regs->ACLKXCTL = CSL_FMKT( MCASP_ACLKXCTL_CLKXP, RISINGEDGE) | CSL_FMKT( MCASP_ACLKXCTL_ASYNC, SYNC ) | CSL_FMKT( MCASP_ACLKXCTL_CLKXM, EXTERNAL ) ; // For Audio clock: MCASP0 // Input clock (AUXCLK) is 12MHz. // HCLK is 12 MHz. mcasp->regs->AHCLKXCTL = CSL_FMKT( MCASP_AHCLKXCTL_HCLKXM , INTERNAL )| CSL_FMKT( MCASP_AHCLKXCTL_HCLKXP , NOTINVERTED)| CSL_FMK ( MCASP_AHCLKXCTL_HCLKXDIV, 0 ); mcasp->regs->XTDM = 0x000000FF; // use only slots 1 and 2. mcasp->regs->XINTCTL = CSL_FMKT( MCASP_XINTCTL_XSTAFRM , DISABLE ) | CSL_FMKT( MCASP_XINTCTL_XDATA , DISABLE ) | CSL_FMKT( MCASP_XINTCTL_XLAST , DISABLE ) | CSL_FMKT( MCASP_XINTCTL_XDMAERR , ENABLE ) | CSL_FMKT( MCASP_XINTCTL_XCKFAIL , DISABLE ) | CSL_FMKT( MCASP_XINTCTL_XSYNCERR, ENABLE ) | CSL_FMKT( MCASP_XINTCTL_XUNDRN , ENABLE ) ; mcasp->regs->XCLKCHK = ( 255 << CSL_MCASP_XCLKCHK_XMAX_SHIFT) | ( 0 << CSL_MCASP_XCLKCHK_XMIN_SHIFT) | ( 1 << CSL_MCASP_XCLKCHK_XPS_SHIFT); // // 3.c: Serializer registers SRCTL[n] // // Microphone data is on serializer 8 mcasp->regs->SRCTL8 = CSL_FMKT ( MCASP_SRCTL8_SRMOD, RCV); // speaker data is on serializer 7 mcasp->regs->SRCTL7 = CSL_FMKT( MCASP_SRCTL7_DISMOD, LOW) | CSL_FMKT( MCASP_SRCTL7_SRMOD, XMT ) ; // // 3.d: global registers: PFUNC, PDIR, DITCTL, DLBCTL, AMUTE // mcasp->regs->PFUNC = 0; // leave all pins as mcasp pins. gpios are handled by chip-level pin mux. mcasp->regs->PDIR = // the only output pins are: AHCLKX and serializer 7 CSL_FMKT( MCASP_PDIR_AHCLKX, OUTPUT) | CSL_FMKT( MCASP_PDIR_AXR7, OUTPUT ) ; mcasp->regs->DITCTL = 0; // DIT not used here mcasp->regs->DLBCTL = 0; // This could be useful for loopback testing. mcasp->regs->AMUTE = 0; // no need for messing with mute. // // 3.e: DIT registers: DITSCRA[N] DITCSRB[N], DITUDRA[N], DITUDRB[N] // // DIT is unused here. // // Step 4: Start high frequency clocks. // // 4.a: take it out of reset mcasp->regs->GBLCTL |= CSL_FMKT(MCASP_GBLCTL_XHCLKRST, ACTIVE) | CSL_FMKT(MCASP_GBLCTL_RHCLKRST, ACTIVE); // Wait until it's out of reset while (!CSL_FEXT(mcasp->regs->GBLCTL, MCASP_GBLCTL_XHCLKRST)); while (!CSL_FEXT(mcasp->regs->GBLCTL, MCASP_GBLCTL_RHCLKRST)); // // Step 5: start serial clocks ACLKX and ACLKR. // // 5.a RCLKRST AND/OR XCLKRST = ACTIVE. // 5.b read back, and wait for it to become active. // mcasp->regs->GBLCTL |= CSL_FMKT(MCASP_GBLCTL_XCLKRST, ACTIVE) | CSL_FMKT(MCASP_GBLCTL_RCLKRST, ACTIVE) ; while (!CSL_FEXT(mcasp->regs->GBLCTL, MCASP_GBLCTL_XCLKRST)); while (!CSL_FEXT(mcasp->regs->GBLCTL, MCASP_GBLCTL_RCLKRST)); clock_failure_detect_setup(); // Step 6: Setup data acquisition // 6.a: if serviced with DMA, set up DMA audio_setup_dma(); // 6.b: if interrupt is used enable transmit/receive interrupt. audio_enable_interrupts(); // 6.c: if polling don't do anything. // // Step 7: Activate serializers // // 7.a: clear status mcasp->regs->XSTAT = 0xFFFF; mcasp->regs->RSTAT = 0xFFFF; // 7.b: take serializers out of reset mcasp->regs->GBLCTL |= CSL_FMKT( MCASP_GBLCTL_RSRCLR, ACTIVE) | CSL_FMKT( MCASP_GBLCTL_XSRCLR, ACTIVE); while (!CSL_FEXT(mcasp->regs->GBLCTL, MCASP_GBLCTL_RSRCLR)); while (!CSL_FEXT(mcasp->regs->GBLCTL, MCASP_GBLCTL_XSRCLR)); // // Step 8: service the xmit buffer // while (CSL_FEXT(mcasp->regs->XSTAT, MCASP_XSTAT_XDATA)); //mcasp->data->DATA_PORT = 0xca1eb; // // Step 9: release state machines from reset // // 9.a: set RSMRST and XSMRST mcasp->regs->GBLCTL |= CSL_FMKT(MCASP_GBLCTL_RSMRST, ACTIVE) | CSL_FMKT(MCASP_GBLCTL_XSMRST, ACTIVE); while (CSL_FEXT(mcasp->regs->GBLCTL, MCASP_GBLCTL_RSMRST) == 0); while (CSL_FEXT(mcasp->regs->GBLCTL, MCASP_GBLCTL_XSMRST) == 0); // // Step 10: Release frame sync generators from reset // This is necessary even when using external frame syncs. // // 10.a: mcasp->regs->GBLCTL |= CSL_FMKT(MCASP_GBLCTL_RFRST, ACTIVE) | CSL_FMKT(MCASP_GBLCTL_XFRST, ACTIVE) ; while (CSL_FEXT(mcasp->regs->GBLCTL, MCASP_GBLCTL_RFRST) == 0); while (CSL_FEXT(mcasp->regs->GBLCTL, MCASP_GBLCTL_XFRST) == 0); // // Step 11: I think we're going here.... // } void clock_failure_detect_setup(void) { int failure = 1; // Setup from McASP 2.4.7.6.1 // 1.a while (failure) { int xstat; // 1.b mcasp->regs->XSTAT = 1 << CSL_MCASP_XSTAT_XCKFAIL_SHIFT; // 1.c TSK_sleep(1); // 1.d, 1.e xstat = mcasp->regs->XSTAT & (1 << CSL_MCASP_XSTAT_XCKFAIL_SHIFT); if (xstat == 0) { failure = 0; } } // 1.f mcasp->regs->XINTCTL |= 1 << CSL_MCASP_XINTCTL_XCKFAIL_SHIFT; // 2.a failure = 1; while (failure) { int xstat; // 1.b mcasp->regs->RSTAT = 1 << CSL_MCASP_RSTAT_RCKFAIL_SHIFT; // 1.c TSK_sleep(1); // 1.d, 1.e xstat = mcasp->regs->RSTAT & (1 << CSL_MCASP_RSTAT_RCKFAIL_SHIFT); if (xstat == 0) { failure = 0; } } // 1.f mcasp->regs->RINTCTL |= 1 << CSL_MCASP_RINTCTL_RCKFAIL_SHIFT; } #define RX_PARAM_SET 0 /* Event 0 is mapped to McASP Receive */ #define RX_RELOAD_SET 64 #define TX_PARAM_SET 1 /* Event 1 is mapped to McASP Transmit */ #define TX_RELOAD_SET 65 #define LINK_ADDR(x) (0x4000 + (x << 5)) void audio_setup_dma(void) { int i, j; dma_regs->DRA[0].DRAE = 0; //(1 << 0); Assign DMA channel 0 to shadown reigon 0; dma_regs->DRA[1].DRAE = 0xFFFFFFFF; // Only reigon 1 is enabled on C674x dma_regs->DRA[2].DRAE = 0; //(1 << 0); dma_regs->DRA[3].DRAE = 0; //(1 << 0); for (i = 0; i < TX_BLOCKSIZE; i++) { for (j = 0; j < TX_CHANNELS; j++) { audio_tx_buffer0[i*TX_CHANNELS+j] = i; audio_tx_buffer1[i*TX_CHANNELS+j] = i; } } for (i = 0; i < RX_BLOCKSIZE; i++) { for (j = 0; j < RX_CHANNELS; j++) { audio_rx_buffer0[i*RX_CHANNELS+j] = i; audio_rx_buffer1[i*RX_CHANNELS+j] = i; } } assert(dma_regs->REVID == 0x40019b00, "Your DMA peripheral does not seem to be enabled"); dma_regs->SHADOW[1].ICR = 0xFFFFFFFF; ECM_enableEvent(8); ECM_enableEvent(56); ECM_enableEvent(57); ECM_enableEvent(58); // On C674x, only reigon 1 has interrupts! // Set up receive parameters dma_regs->PARAMSET[RX_PARAM_SET].OPT = CSL_FMK (EDMA3CC_OPT_TCC, 0 ) | // channel completion code 0 CSL_FMKT(EDMA3CC_OPT_TCINTEN, ENABLE) ; // ENABLE interrupt on completion dma_regs->PARAMSET[RX_PARAM_SET].SRC = (Uint32) &(mcasp->data->DATA_PORT); dma_regs->PARAMSET[RX_PARAM_SET].A_B_CNT = (RX_BLOCKSIZE_BYTES << 16) | 1; // 1 in the 2nd dimension dma_regs->PARAMSET[RX_PARAM_SET].DST = (Uint32) audio_rx_buffer0; dma_regs->PARAMSET[RX_PARAM_SET].SRC_DST_BIDX = (1 << 16) | 0; // DSTBIDX, SRCBIDX dma_regs->PARAMSET[RX_PARAM_SET].LINK_BCNTRLD = (RX_BLOCKSIZE_BYTES << 16) | LINK_ADDR(RX_RELOAD_SET); // BCNTRLD, LINK dma_regs->PARAMSET[RX_PARAM_SET].SRC_DST_CIDX = (0 << 16) | 0; // 3RD DIMENSION indexes. DST,SRC dma_regs->PARAMSET[RX_PARAM_SET].CCNT = 1; // index for 3rd dimension. dma_regs->PARAMSET[RX_RELOAD_SET] = dma_regs->PARAMSET[RX_PARAM_SET]; // Set up receive parameters dma_regs->PARAMSET[TX_PARAM_SET].OPT = (1 << CSL_EDMA3CC_OPT_TCC_SHIFT ) | // channel completion code 0 (1 << CSL_EDMA3CC_OPT_TCINTEN_SHIFT); // ENABLE interrupt on completion dma_regs->PARAMSET[TX_PARAM_SET].SRC = (Uint32) audio_tx_buffer0; dma_regs->PARAMSET[TX_PARAM_SET].A_B_CNT = (TX_BLOCKSIZE_BYTES << 16) | 1; // 1 in the 2nd dimension dma_regs->PARAMSET[TX_PARAM_SET].DST = (Uint32) &(mcasp->data->DATA_PORT); dma_regs->PARAMSET[TX_PARAM_SET].SRC_DST_BIDX = (0 << 16) | 1; // DSTBIDX, SRCBIDX dma_regs->PARAMSET[TX_PARAM_SET].LINK_BCNTRLD = (TX_BLOCKSIZE_BYTES << 16) | LINK_ADDR(TX_RELOAD_SET); // BCNTRLD, LINK dma_regs->PARAMSET[TX_PARAM_SET].SRC_DST_CIDX = (0 << 16) | 0; // 3RD DIMENSION indexes. DST,SRC dma_regs->PARAMSET[TX_PARAM_SET].CCNT = 1; // index for 3rd dimension. dma_regs->PARAMSET[TX_RELOAD_SET] = dma_regs->PARAMSET[TX_PARAM_SET]; dma_regs->SHADOW[1].IESR = (1 << 0) | (1 << 1); // (1<<0); // enable interrupts for E0, E1 completion // dma_regs->SHADOW[1].ESR = (1 << 0) | (1 << 1); // Trigger event E0 manually. Don't do this dma_regs->SHADOW[1].EESR = (1 << 0) | (1 << 1); // (1<<0); // enable events for E0, E1 completion } void audio_enable_interrupts(void) { // C64_enableIER(1 << 6); mcasp->regs->XSTAT = 0xFFFF; mcasp->regs->RSTAT = 0xFFFF; ECM_enableEvent(61); }