summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx31/gigabeat-s/i2s-gigabeat-s.c
diff options
context:
space:
mode:
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.c93
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
25void i2s_reset(void) 27void 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}