diff options
Diffstat (limited to 'firmware/target/arm/imx31/gigabeat-s/i2s-gigabeat-s.c')
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/i2s-gigabeat-s.c | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/firmware/target/arm/imx31/gigabeat-s/i2s-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/i2s-gigabeat-s.c index 6291a9cf18..723999c15e 100644 --- a/firmware/target/arm/imx31/gigabeat-s/i2s-gigabeat-s.c +++ b/firmware/target/arm/imx31/gigabeat-s/i2s-gigabeat-s.c | |||
@@ -20,6 +20,8 @@ | |||
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | #include "config.h" | 21 | #include "config.h" |
22 | #include "system.h" | 22 | #include "system.h" |
23 | #include "ccm-imx31.h" | ||
24 | #include "sdma-imx31.h" | ||
23 | #include "i2s.h" | 25 | #include "i2s.h" |
24 | 26 | ||
25 | void i2s_reset(void) | 27 | void i2s_reset(void) |
@@ -42,4 +44,95 @@ void i2s_reset(void) | |||
42 | ((64-1) << CCM_PDR1_SSI2_PODF_POS), | 44 | ((64-1) << CCM_PDR1_SSI2_PODF_POS), |
43 | CCM_PDR1_SSI1_PODF | CCM_PDR1_SSI2_PODF | | 45 | CCM_PDR1_SSI1_PODF | CCM_PDR1_SSI2_PODF | |
44 | CCM_PDR1_SSI1_PRE_PODF | CCM_PDR1_SSI2_PRE_PODF); | 46 | CCM_PDR1_SSI1_PRE_PODF | CCM_PDR1_SSI2_PRE_PODF); |
47 | |||
48 | ccm_module_clock_gating(CG_SSI1, CGM_ON_RUN_WAIT); | ||
49 | ccm_module_clock_gating(CG_SSI2, CGM_ON_RUN_WAIT); | ||
50 | |||
51 | /* Reset & disable SSIs */ | ||
52 | SSI_SCR1 &= ~SSI_SCR_SSIEN; | ||
53 | SSI_SCR2 &= ~SSI_SCR_SSIEN; | ||
54 | |||
55 | SSI_SIER1 = 0; | ||
56 | SSI_SIER2 = 0; | ||
57 | |||
58 | /* Set up audio mux */ | ||
59 | |||
60 | /* Port 2 (internally connected to SSI2) | ||
61 | * All clocking is output sourced from port 4 */ | ||
62 | AUDMUX_PTCR2 = AUDMUX_PTCR_TFS_DIR | AUDMUX_PTCR_TFSEL_PORT4 | | ||
63 | AUDMUX_PTCR_TCLKDIR | AUDMUX_PTCR_TCSEL_PORT4 | | ||
64 | AUDMUX_PTCR_SYN; | ||
65 | |||
66 | /* Receive data from port 4 */ | ||
67 | AUDMUX_PDCR2 = AUDMUX_PDCR_RXDSEL_PORT4; | ||
68 | /* All clock lines are inputs sourced from the master mode codec and | ||
69 | * sent back to SSI2 through port 2 */ | ||
70 | AUDMUX_PTCR4 = AUDMUX_PTCR_SYN; | ||
71 | |||
72 | /* Receive data from port 2 */ | ||
73 | AUDMUX_PDCR4 = AUDMUX_PDCR_RXDSEL_PORT2; | ||
74 | |||
75 | /* PORT1 (internally connected to SSI1) routes clocking to PORT5 to | ||
76 | * provide MCLK to the codec */ | ||
77 | /* TX clocks are inputs taken from SSI2 */ | ||
78 | /* RX clocks are outputs taken from PORT4 */ | ||
79 | AUDMUX_PTCR1 = AUDMUX_PTCR_RFS_DIR | AUDMUX_PTCR_RFSSEL_PORT4 | | ||
80 | AUDMUX_PTCR_RCLKDIR | AUDMUX_PTCR_RCSEL_PORT4; | ||
81 | /* RX data taken from PORT4 */ | ||
82 | AUDMUX_PDCR1 = AUDMUX_PDCR_RXDSEL_PORT4; | ||
83 | |||
84 | /* PORT5 outputs TCLK sourced from PORT1 (SSI1) */ | ||
85 | AUDMUX_PTCR5 = AUDMUX_PTCR_TCLKDIR | AUDMUX_PTCR_TCSEL_PORT1; | ||
86 | AUDMUX_PDCR5 = 0; | ||
87 | |||
88 | /* Setup SSIs */ | ||
89 | |||
90 | /* SSI2 - SoC software interface for all I2S data out */ | ||
91 | SSI_SCR2 = SSI_SCR_SYN | SSI_SCR_I2S_MODE_SLAVE; | ||
92 | SSI_STCR2 = SSI_STCR_TXBIT0 | SSI_STCR_TSCKP | SSI_STCR_TFSI | | ||
93 | SSI_STCR_TEFS | SSI_STCR_TFEN0; | ||
94 | |||
95 | /* 16 bits per word, 2 words per frame */ | ||
96 | SSI_STCCR2 = SSI_STRCCR_WL16 | ((2-1) << SSI_STRCCR_DC_POS) | | ||
97 | ((4-1) << SSI_STRCCR_PM_POS); | ||
98 | |||
99 | /* Transmit low watermark */ | ||
100 | SSI_SFCSR2 = (SSI_SFCSR2 & ~SSI_SFCSR_TFWM0) | | ||
101 | ((8-SDMA_SSI_TXFIFO_WML) << SSI_SFCSR_TFWM0_POS); | ||
102 | SSI_STMSK2 = 0; | ||
103 | |||
104 | /* SSI1 - provides MCLK to codec. Receives data from codec. */ | ||
105 | SSI_STCR1 = SSI_STCR_TXDIR; | ||
106 | |||
107 | /* f(INT_BIT_CLK) = | ||
108 | * f(SYS_CLK) / [(DIV2 + 1)*(7*PSR + 1)*(PM + 1)*2] = | ||
109 | * 677737600 / [(1 + 1)*(7*0 + 1)*(0 + 1)*2] = | ||
110 | * 677737600 / 4 = 169344000 Hz | ||
111 | * | ||
112 | * 45.4.2.2 DIV2, PSR, and PM Bit Description states: | ||
113 | * Bits DIV2, PSR, and PM should not be all set to zero at the same | ||
114 | * time. | ||
115 | * | ||
116 | * The hardware seems to force a divide by 4 even if all bits are | ||
117 | * zero but comply by setting DIV2 and the others to zero. | ||
118 | */ | ||
119 | SSI_STCCR1 = SSI_STRCCR_DIV2 | ((1-1) << SSI_STRCCR_PM_POS); | ||
120 | |||
121 | /* SSI1 - receive - asynchronous clocks */ | ||
122 | SSI_SCR1 = SSI_SCR_I2S_MODE_SLAVE; | ||
123 | |||
124 | SSI_SRCR1 = SSI_SRCR_RXBIT0 | SSI_SRCR_RSCKP | SSI_SRCR_RFSI | | ||
125 | SSI_SRCR_REFS; | ||
126 | |||
127 | /* 16 bits per word, 2 words per frame */ | ||
128 | SSI_SRCCR1 = SSI_STRCCR_WL16 | ((2-1) << SSI_STRCCR_DC_POS) | | ||
129 | ((4-1) << SSI_STRCCR_PM_POS); | ||
130 | |||
131 | /* Receive high watermark */ | ||
132 | SSI_SFCSR1 = (SSI_SFCSR1 & ~SSI_SFCSR_RFWM0) | | ||
133 | (SDMA_SSI_RXFIFO_WML << SSI_SFCSR_RFWM0_POS); | ||
134 | SSI_SRMSK1 = 0; | ||
135 | |||
136 | /* Enable SSI1 (codec clock) */ | ||
137 | SSI_SCR1 |= SSI_SCR_SSIEN; | ||
45 | } | 138 | } |