From d1adf35e626cd9717cab2de17b029d3c8790ce6e Mon Sep 17 00:00:00 2001 From: Michael Sevakis Date: Mon, 9 Mar 2009 04:25:25 +0000 Subject: Gigabeat S: Switch SSI1 and 2 around so that playback can use the shared peripheral DMA with SSI2 which doesn't require use of the peripheral DMA unit-- SSI2 is mapped to the SDMA core address space. Fix some break keywords in get_script_pc(). Use the patched script for mcu_2_app (BSP appears to have neglected to update that). Use _SHP instead of _SP for shared peripheral constants (consistency). git-svn-id: svn://svn.rockbox.org/rockbox/trunk@20254 a1c6a512-1295-4272-9138-f99709370657 --- .../target/arm/imx31/gigabeat-s/audio-gigabeat-s.c | 4 +- firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c | 116 ++++++++++----------- .../target/arm/imx31/gigabeat-s/wmcodec-imx31.c | 8 +- firmware/target/arm/imx31/sdma-imx31.c | 31 ++---- firmware/target/arm/imx31/sdma-imx31.h | 10 +- 5 files changed, 77 insertions(+), 92 deletions(-) diff --git a/firmware/target/arm/imx31/gigabeat-s/audio-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/audio-gigabeat-s.c index 87b59de599..f5e17a4039 100644 --- a/firmware/target/arm/imx31/gigabeat-s/audio-gigabeat-s.c +++ b/firmware/target/arm/imx31/gigabeat-s/audio-gigabeat-s.c @@ -30,8 +30,8 @@ void audio_set_output_source(int source) { default: case AUDIO_SRC_PLAYBACK: - /* Receive data from PORT1 (SSI1) */ - AUDMUX_PDCR4 = AUDMUX_PDCR_RXDSEL_PORT1; + /* Receive data from PORT2 (SSI2) */ + AUDMUX_PDCR4 = AUDMUX_PDCR_RXDSEL_PORT2; /* wmc_clear(WMC_COMPANDING_CTRL, WMC_LOOPBACK); */ break; diff --git a/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c b/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c index 9d2503f4e6..649186ab2e 100644 --- a/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c @@ -88,7 +88,7 @@ static void play_dma_callback(void) void pcm_play_lock(void) { if (++dma_play_data.locked == 1) - imx31_regclr32(&SSI_SIER1, SSI_SIER_TDMAE); + imx31_regclr32(&SSI_SIER2, SSI_SIER_TDMAE); } void pcm_play_unlock(void) @@ -98,7 +98,7 @@ void pcm_play_unlock(void) int oldstatus = disable_irq_save(); int pending = dma_play_data.callback_pending; dma_play_data.callback_pending = 0; - SSI_SIER1 |= SSI_SIER_TDMAE; + SSI_SIER2 |= SSI_SIER_TDMAE; restore_irq(oldstatus); /* Should an interrupt be forced instead? The upper pcm layer can @@ -119,11 +119,11 @@ void pcm_play_dma_init(void) /* Init channel information */ dma_play_cd.bd_count = 1; dma_play_cd.callback = play_dma_callback; - dma_play_cd.shp_addr = SDMA_PER_ADDR_SSI1_TX1; + dma_play_cd.shp_addr = SDMA_PER_ADDR_SSI2_TX1; dma_play_cd.wml = SDMA_SSI_TXFIFO_WML*2; - dma_play_cd.per_type = SDMA_PER_SSI; + dma_play_cd.per_type = SDMA_PER_SSI_SHP; /* SSI2 shared with SDMA core */ dma_play_cd.tran_type = SDMA_TRAN_EMI_2_PER; - dma_play_cd.event_id1 = SDMA_REQ_SSI1_TX1; + dma_play_cd.event_id1 = SDMA_REQ_SSI2_TX1; sdma_channel_init(DMA_PLAY_CH_NUM, &dma_play_cd, &dma_play_bd); @@ -131,60 +131,60 @@ void pcm_play_dma_init(void) imx31_clkctl_module_clock_gating(CG_SSI2, CGM_ON_ALL); /* Reset & disable SSIs */ - SSI_SCR2 &= ~SSI_SCR_SSIEN; SSI_SCR1 &= ~SSI_SCR_SSIEN; + SSI_SCR2 &= ~SSI_SCR_SSIEN; SSI_SIER1 = 0; SSI_SIER2 = 0; /* Set up audio mux */ - /* Port 1 (internally connected to SSI1) + /* Port 2 (internally connected to SSI2) * All clocking is output sourced from port 4 */ - AUDMUX_PTCR1 = AUDMUX_PTCR_TFS_DIR | AUDMUX_PTCR_TFSEL_PORT4 | + AUDMUX_PTCR2 = AUDMUX_PTCR_TFS_DIR | AUDMUX_PTCR_TFSEL_PORT4 | AUDMUX_PTCR_TCLKDIR | AUDMUX_PTCR_TCSEL_PORT4 | AUDMUX_PTCR_SYN; /* Receive data from port 4 */ - AUDMUX_PDCR1 = AUDMUX_PDCR_RXDSEL_PORT4; + AUDMUX_PDCR2 = AUDMUX_PDCR_RXDSEL_PORT4; /* All clock lines are inputs sourced from the master mode codec and - * sent back to SSI1 through port 1 */ + * sent back to SSI2 through port 2 */ AUDMUX_PTCR4 = AUDMUX_PTCR_SYN; - /* Receive data from port 1 */ - AUDMUX_PDCR4 = AUDMUX_PDCR_RXDSEL_PORT1; + /* Receive data from port 2 */ + AUDMUX_PDCR4 = AUDMUX_PDCR_RXDSEL_PORT2; - /* PORT2 (internally connected to SSI2) routes clocking to PORT5 to + /* PORT1 (internally connected to SSI1) routes clocking to PORT5 to * provide MCLK to the codec */ /* TX clocks are inputs taken from SSI2 */ /* RX clocks are outputs taken from PORT4 */ - AUDMUX_PTCR2 = AUDMUX_PTCR_RFS_DIR | AUDMUX_PTCR_RFSSEL_PORT4 | + AUDMUX_PTCR1 = AUDMUX_PTCR_RFS_DIR | AUDMUX_PTCR_RFSSEL_PORT4 | AUDMUX_PTCR_RCLKDIR | AUDMUX_PTCR_RCSEL_PORT4; /* RX data taken from PORT4 */ - AUDMUX_PDCR2 = AUDMUX_PDCR_RXDSEL_PORT4; + AUDMUX_PDCR1 = AUDMUX_PDCR_RXDSEL_PORT4; - /* PORT5 outputs TCLK sourced from PORT2 (SSI2) */ - AUDMUX_PTCR5 = AUDMUX_PTCR_TCLKDIR | AUDMUX_PTCR_TCSEL_PORT2; + /* PORT5 outputs TCLK sourced from PORT1 (SSI1) */ + AUDMUX_PTCR5 = AUDMUX_PTCR_TCLKDIR | AUDMUX_PTCR_TCSEL_PORT1; AUDMUX_PDCR5 = 0; /* Setup SSIs */ - /* SSI1 - SoC software interface for all I2S data out */ - SSI_SCR1 = SSI_SCR_SYN | SSI_SCR_I2S_MODE_SLAVE; - SSI_STCR1 = SSI_STCR_TXBIT0 | SSI_STCR_TSCKP | SSI_STCR_TFSI | + /* SSI2 - SoC software interface for all I2S data out */ + SSI_SCR2 = SSI_SCR_SYN | SSI_SCR_I2S_MODE_SLAVE; + SSI_STCR2 = SSI_STCR_TXBIT0 | SSI_STCR_TSCKP | SSI_STCR_TFSI | SSI_STCR_TEFS | SSI_STCR_TFEN0; /* 16 bits per word, 2 words per frame */ - SSI_STCCR1 = SSI_STRCCR_WL16 | SSI_STRCCR_DCw(2-1) | + SSI_STCCR2 = SSI_STRCCR_WL16 | SSI_STRCCR_DCw(2-1) | SSI_STRCCR_PMw(4-1); /* Transmit low watermark */ - SSI_SFCSR1 = (SSI_SFCSR1 & ~SSI_SFCSR_TFWM0) | + SSI_SFCSR2 = (SSI_SFCSR2 & ~SSI_SFCSR_TFWM0) | SSI_SFCSR_TFWM0w(8-SDMA_SSI_TXFIFO_WML); - SSI_STMSK1 = 0; + SSI_STMSK2 = 0; - /* SSI2 - provides MCLK to codec. Receives data from codec. */ - SSI_STCR2 = SSI_STCR_TXDIR; + /* SSI1 - provides MCLK to codec. Receives data from codec. */ + SSI_STCR1 = SSI_STCR_TXDIR; /* f(INT_BIT_CLK) = * f(SYS_CLK) / [(DIV2 + 1)*(7*PSR + 1)*(PM + 1)*2] = @@ -198,25 +198,25 @@ void pcm_play_dma_init(void) * The hardware seems to force a divide by 4 even if all bits are * zero but comply by setting DIV2 and the others to zero. */ - SSI_STCCR2 = SSI_STRCCR_DIV2 | SSI_STRCCR_PMw(1-1); + SSI_STCCR1 = SSI_STRCCR_DIV2 | SSI_STRCCR_PMw(1-1); - /* SSI2 - receive - asynchronous clocks */ - SSI_SCR2 = SSI_SCR_I2S_MODE_SLAVE; + /* SSI1 - receive - asynchronous clocks */ + SSI_SCR1 = SSI_SCR_I2S_MODE_SLAVE; - SSI_SRCR2 = SSI_SRCR_RXBIT0 | SSI_SRCR_RSCKP | SSI_SRCR_RFSI | + SSI_SRCR1 = SSI_SRCR_RXBIT0 | SSI_SRCR_RSCKP | SSI_SRCR_RFSI | SSI_SRCR_REFS; /* 16 bits per word, 2 words per frame */ - SSI_SRCCR2 = SSI_STRCCR_WL16 | SSI_STRCCR_DCw(2-1) | + SSI_SRCCR1 = SSI_STRCCR_WL16 | SSI_STRCCR_DCw(2-1) | SSI_STRCCR_PMw(4-1); /* Receive high watermark */ - SSI_SFCSR2 = (SSI_SFCSR2 & ~SSI_SFCSR_RFWM0) | + SSI_SFCSR1 = (SSI_SFCSR1 & ~SSI_SFCSR_RFWM0) | SSI_SFCSR_RFWM0w(SDMA_SSI_RXFIFO_WML); - SSI_SRMSK2 = 0; + SSI_SRMSK1 = 0; - /* Enable SSI2 (codec clock) */ - SSI_SCR2 |= SSI_SCR_SSIEN; + /* Enable SSI1 (codec clock) */ + SSI_SCR1 |= SSI_SCR_SSIEN; audiohw_init(); } @@ -229,31 +229,31 @@ void pcm_postinit(void) static void play_start_pcm(void) { /* Stop transmission (if in progress) */ - SSI_SCR1 &= ~SSI_SCR_TE; + SSI_SCR2 &= ~SSI_SCR_TE; - SSI_SCR1 |= SSI_SCR_SSIEN; /* Enable SSI */ - SSI_STCR1 |= SSI_STCR_TFEN0; /* Enable TX FIFO */ + SSI_SCR2 |= SSI_SCR_SSIEN; /* Enable SSI */ + SSI_STCR2 |= SSI_STCR_TFEN0; /* Enable TX FIFO */ dma_play_data.state = 1; /* Enable DMA requests on unlock */ /* Do prefill to prevent swapped channels (see TLSbo61214 in MCIMX31CE). * No actual solution was offered but this appears to work. */ - SSI_STX0_1 = 0; - SSI_STX0_1 = 0; - SSI_STX0_1 = 0; - SSI_STX0_1 = 0; + SSI_STX0_2 = 0; + SSI_STX0_2 = 0; + SSI_STX0_2 = 0; + SSI_STX0_2 = 0; - SSI_SCR1 |= SSI_SCR_TE; /* Start transmitting */ + SSI_SCR2 |= SSI_SCR_TE; /* Start transmitting */ } static void play_stop_pcm(void) { /* Wait for FIFO to empty */ - while (SSI_SFCSR_TFCNT0r(SSI_SFCSR1) > 0); + while (SSI_SFCSR_TFCNT0r(SSI_SFCSR2) > 0); /* Disable transmission */ - SSI_STCR1 &= ~SSI_STCR_TFEN0; - SSI_SCR1 &= ~(SSI_SCR_TE | SSI_SCR_SSIEN); + SSI_STCR2 &= ~SSI_STCR_TFEN0; + SSI_SCR2 &= ~(SSI_SCR_TE | SSI_SCR_SSIEN); /* Set state before pending to prevent race with interrupt */ /* Do not enable DMA requests on unlock */ @@ -266,8 +266,8 @@ void pcm_play_dma_start(const void *addr, size_t size) sdma_channel_stop(DMA_PLAY_CH_NUM); /* Disable transmission */ - SSI_STCR1 &= ~SSI_STCR_TFEN0; - SSI_SCR1 &= ~(SSI_SCR_TE | SSI_SCR_SSIEN); + SSI_STCR2 &= ~SSI_STCR_TFEN0; + SSI_SCR2 &= ~(SSI_SCR_TE | SSI_SCR_SSIEN); addr = (void *)(((unsigned long)addr + 3) & ~3); size &= ~3; @@ -408,7 +408,7 @@ static void rec_dma_callback(void) void pcm_rec_lock(void) { if (++dma_rec_data.locked == 1) - imx31_regclr32(&SSI_SIER2, SSI_SIER_RDMAE); + imx31_regclr32(&SSI_SIER1, SSI_SIER_RDMAE); } void pcm_rec_unlock(void) @@ -418,7 +418,7 @@ void pcm_rec_unlock(void) int oldstatus = disable_irq_save(); int pending = dma_rec_data.callback_pending; dma_rec_data.callback_pending = 0; - SSI_SIER2 |= SSI_SIER_RDMAE; + SSI_SIER1 |= SSI_SIER_RDMAE; restore_irq(oldstatus); /* Should an interrupt be forced instead? The upper pcm layer can @@ -451,10 +451,10 @@ void pcm_rec_dma_stop(void) /* Stop receiving data */ sdma_channel_stop(DMA_REC_CH_NUM); - imx31_regclr32(&SSI_SIER2, SSI_SIER_RDMAE); + imx31_regclr32(&SSI_SIER1, SSI_SIER_RDMAE); - SSI_SCR2 &= ~SSI_SCR_RE; /* Disable RX */ - SSI_SRCR2 &= ~SSI_SRCR_RFEN0; /* Disable RX FIFO */ + SSI_SCR1 &= ~SSI_SCR_RE; /* Disable RX */ + SSI_SRCR1 &= ~SSI_SRCR_RFEN0; /* Disable RX FIFO */ /* Set state before pending to prevent race with interrupt */ /* Do not enable DMA requests on unlock */ @@ -487,14 +487,14 @@ void pcm_rec_dma_start(void *addr, size_t size) dma_rec_data.state = 1; - SSI_SRCR2 |= SSI_SRCR_RFEN0; /* Enable RX FIFO */ + SSI_SRCR1 |= SSI_SRCR_RFEN0; /* Enable RX FIFO */ /* Ensure clear FIFO */ - while (SSI_SFCSR2 & SSI_SFCSR_RFCNT0) - SSI_SRX0_2; + while (SSI_SFCSR1 & SSI_SFCSR_RFCNT0) + SSI_SRX0_1; /* Enable receive */ - SSI_SCR2 |= SSI_SCR_RE; + SSI_SCR1 |= SSI_SCR_RE; sdma_channel_run(DMA_REC_CH_NUM); } @@ -511,11 +511,11 @@ void pcm_rec_dma_init(void) /* Init channel information */ dma_rec_cd.bd_count = 1; dma_rec_cd.callback = rec_dma_callback; - dma_rec_cd.shp_addr = SDMA_PER_ADDR_SSI2_RX1; + dma_rec_cd.shp_addr = SDMA_PER_ADDR_SSI1_RX1; dma_rec_cd.wml = SDMA_SSI_RXFIFO_WML*2; dma_rec_cd.per_type = SDMA_PER_SSI; dma_rec_cd.tran_type = SDMA_TRAN_PER_2_EMI; - dma_rec_cd.event_id1 = SDMA_REQ_SSI2_RX1; + dma_rec_cd.event_id1 = SDMA_REQ_SSI1_RX1; sdma_channel_init(DMA_REC_CH_NUM, &dma_rec_cd, &dma_rec_bd); } diff --git a/firmware/target/arm/imx31/gigabeat-s/wmcodec-imx31.c b/firmware/target/arm/imx31/gigabeat-s/wmcodec-imx31.c index e307057978..542f6eb633 100644 --- a/firmware/target/arm/imx31/gigabeat-s/wmcodec-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/wmcodec-imx31.c @@ -44,17 +44,17 @@ void audiohw_init(void) /* How SYSCLK for codec is derived (USBPLL=338.688MHz). * * SSI post dividers (SSI2 PODF=4, SSI2 PRE PODF=0): - * 338688000Hz / 5 = 67737600Hz = ssi2_clk + * 338688000Hz / 5 = 67737600Hz = ssi1_clk * * SSI bit clock dividers (DIV2=1, PSR=0, PM=0): - * ssi2_clk / 4 = 16934400Hz = INT_BIT_CLK (MCLK) + * ssi1_clk / 4 = 16934400Hz = INT_BIT_CLK (MCLK) * * WM Codec post divider (MCLKDIV=1.5): * INT_BIT_CLK (MCLK) / 1.5 = 11289600Hz = 256*fs = SYSCLK */ imx31_regmod32(&CLKCTL_PDR1, - PDR1_SSI1_PODFw(64-1) | PDR1_SSI2_PODFw(5-1) | - PDR1_SSI1_PRE_PODFw(8-1) | PDR1_SSI2_PRE_PODFw(1-1), + PDR1_SSI1_PODFw(5-1) | PDR1_SSI2_PODFw(64-1) | + PDR1_SSI1_PRE_PODFw(1-1) | PDR1_SSI2_PRE_PODFw(8-1), PDR1_SSI1_PODF | PDR1_SSI2_PODF | PDR1_SSI1_PRE_PODF | PDR1_SSI2_PRE_PODF); diff --git a/firmware/target/arm/imx31/sdma-imx31.c b/firmware/target/arm/imx31/sdma-imx31.c index 100bd51028..d1611d6332 100644 --- a/firmware/target/arm/imx31/sdma-imx31.c +++ b/firmware/target/arm/imx31/sdma-imx31.c @@ -116,7 +116,7 @@ static void init_script_info(void) script_info.ap_2_bp_addr = ap_2_bp_ADDR_2; script_info.bp_2_ap_addr = bp_2_ap_ADDR_2; script_info.loopback_on_dsp_side_addr = -1; - script_info.mcu_2_app_addr = mcu_2_app_ADDR_2; + script_info.mcu_2_app_addr = mcu_2_app_patched_ADDR_2; script_info.mcu_2_shp_addr = mcu_2_shp_patched_ADDR_2; script_info.mcu_interrupt_only_addr = -1; script_info.shp_2_mcu_addr = shp_2_mcu_patched_ADDR_2; @@ -161,8 +161,6 @@ static unsigned long get_script_pc(unsigned int peripheral_type, case SDMA_TRAN_INT_2_EMI: res = script_info.ap_2_ap_addr; break; - default: - break; } break; @@ -182,8 +180,6 @@ static unsigned long get_script_pc(unsigned int peripheral_type, case SDMA_TRAN_EMI_2_DSP_LOOP: res = script_info.mcu_interrupt_only_addr; break; - default: - break; } break; #endif @@ -204,8 +200,6 @@ static unsigned long get_script_pc(unsigned int peripheral_type, case SDMA_TRAN_EMI_2_PER: res = script_info.mcu_2_firi_addr; break; - default: - break; } break; #endif @@ -226,14 +220,12 @@ static unsigned long get_script_pc(unsigned int peripheral_type, case SDMA_TRAN_EMI_2_PER: res = script_info.mcu_2_app_addr; break; - default: - break; } break; #endif #if 0 /* Not using this */ - case SDMA_PER_UART_SP: + case SDMA_PER_UART_SHP: switch (transfer_type) { case SDMA_TRAN_PER_2_INT: @@ -248,8 +240,6 @@ static unsigned long get_script_pc(unsigned int peripheral_type, case SDMA_TRAN_EMI_2_PER: res = script_info.mcu_2_shp_addr; break; - default: - break; } break; #endif @@ -263,8 +253,6 @@ static unsigned long get_script_pc(unsigned int peripheral_type, case SDMA_TRAN_EMI_2_PER: res = script_info.mcu_2_ata_addr; break; - default: - break; } break; @@ -285,8 +273,6 @@ static unsigned long get_script_pc(unsigned int peripheral_type, case SDMA_TRAN_EMI_2_PER: res = script_info.mcu_2_app_addr; break; - default: - break; } break; @@ -294,8 +280,8 @@ static unsigned long get_script_pc(unsigned int peripheral_type, case SDMA_PER_MMC: case SDMA_PER_SDHC: #endif - case SDMA_PER_SSI_SP: - case SDMA_PER_CSPI_SP: + case SDMA_PER_SSI_SHP: + case SDMA_PER_CSPI_SHP: switch (transfer_type) { case SDMA_TRAN_PER_2_INT: @@ -310,9 +296,8 @@ static unsigned long get_script_pc(unsigned int peripheral_type, case SDMA_TRAN_EMI_2_PER: res = script_info.mcu_2_shp_addr; break; - default: - break; } + break; case SDMA_PER_MSHC: switch (transfer_type) @@ -323,9 +308,8 @@ static unsigned long get_script_pc(unsigned int peripheral_type, case SDMA_TRAN_EMI_2_PER: res = script_info.mcu_2_mshc_addr; break; - default: - break; } + break; case SDMA_PER_CCM: switch (transfer_type) @@ -333,9 +317,8 @@ static unsigned long get_script_pc(unsigned int peripheral_type, case SDMA_TRAN_PER_2_EMI: res = script_info.dptc_dvfs_addr; break; - default: - break; } + break; } if (res == (unsigned short)-1) diff --git a/firmware/target/arm/imx31/sdma-imx31.h b/firmware/target/arm/imx31/sdma-imx31.h index 5daa33d7ba..b7e0ab42a4 100644 --- a/firmware/target/arm/imx31/sdma-imx31.h +++ b/firmware/target/arm/imx31/sdma-imx31.h @@ -28,22 +28,24 @@ * script to execute. */ enum SDMA_PERIPHERAL_TYPE { + /* SHP = "Shared peripheral" where peripheral is mapped into SDMA + * core memory via the SPBA */ __SDMA_PER_FIRST = -1, SDMA_PER_MEMORY, SDMA_PER_DSP, SDMA_PER_FIRI, SDMA_PER_UART, - SDMA_PER_UART_SP, /* Shared */ + SDMA_PER_UART_SHP, SDMA_PER_ATA, SDMA_PER_CSPI, SDMA_PER_EXT, SDMA_PER_SSI, - SDMA_PER_SSI_SP, /* Shared */ + SDMA_PER_SSI_SHP, SDMA_PER_MMC, SDMA_PER_SDHC, - SDMA_PER_CSPI_SP, /* Shared */ + SDMA_PER_CSPI_SHP, SDMA_PER_MSHC, - SDMA_PER_MSHC_SP, /* Shared */ + SDMA_PER_MSHC_SHP, SDMA_PER_CCM, SDMA_PER_ASRC, SDMA_PER_ESAI, -- cgit v1.2.3