diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2011-10-17 15:37:14 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2011-10-17 15:37:14 +0000 |
commit | feddfdb2d9e56c132d91d72b6c7a595fa0b83a16 (patch) | |
tree | 52eb3cf18e5cdde0ffa1c06c85668332e9649631 | |
parent | 2a478c826bff003a46a35c4cff2ca961c208c38f (diff) | |
download | rockbox-feddfdb2d9e56c132d91d72b6c7a595fa0b83a16.tar.gz rockbox-feddfdb2d9e56c132d91d72b6c7a595fa0b83a16.zip |
Gigabeat S/i.MX31/wm8978: Clean up clocking information in the general wmcodec/pcm drivers and move it to the target's wmcodec/i2s files.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30771 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | firmware/drivers/audio/wm8978.c | 95 | ||||
-rw-r--r-- | firmware/export/wm8978.h | 11 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/i2s-gigabeat-s.c | 93 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c | 96 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/wmcodec-gigabeat-s.c | 83 |
5 files changed, 190 insertions, 188 deletions
diff --git a/firmware/drivers/audio/wm8978.c b/firmware/drivers/audio/wm8978.c index 6836d8c5e8..5bba19b996 100644 --- a/firmware/drivers/audio/wm8978.c +++ b/firmware/drivers/audio/wm8978.c | |||
@@ -505,88 +505,7 @@ void audiohw_close(void) | |||
505 | 505 | ||
506 | void audiohw_set_frequency(int fsel) | 506 | void audiohw_set_frequency(int fsel) |
507 | { | 507 | { |
508 | /* For 16.9344MHz MCLK, codec as master. */ | 508 | extern const struct wmc_srctrl_entry wmc_srctrl_table[HW_NUM_FREQ]; |
509 | static const struct | ||
510 | { | ||
511 | uint32_t plln : 8; | ||
512 | uint32_t pllk1 : 6; | ||
513 | uint32_t pllk2 : 9; | ||
514 | uint32_t pllk3 : 9; | ||
515 | unsigned char mclkdiv; | ||
516 | unsigned char filter; | ||
517 | } srctrl_table[HW_NUM_FREQ] = | ||
518 | { | ||
519 | [HW_FREQ_8] = /* PLL = 65.536MHz */ | ||
520 | { | ||
521 | .plln = 7 | WMC_PLL_PRESCALE, | ||
522 | .pllk1 = 0x2f, /* 12414886 */ | ||
523 | .pllk2 = 0x0b7, | ||
524 | .pllk3 = 0x1a6, | ||
525 | .mclkdiv = WMC_MCLKDIV_8, /* 2.0480 MHz */ | ||
526 | .filter = WMC_SR_8KHZ, | ||
527 | }, | ||
528 | [HW_FREQ_11] = /* PLL = off */ | ||
529 | { | ||
530 | .mclkdiv = WMC_MCLKDIV_6, /* 2.8224 MHz */ | ||
531 | .filter = WMC_SR_12KHZ, | ||
532 | }, | ||
533 | [HW_FREQ_12] = /* PLL = 73.728 MHz */ | ||
534 | { | ||
535 | .plln = 8 | WMC_PLL_PRESCALE, | ||
536 | .pllk1 = 0x2d, /* 11869595 */ | ||
537 | .pllk2 = 0x08e, | ||
538 | .pllk3 = 0x19b, | ||
539 | .mclkdiv = WMC_MCLKDIV_6, /* 3.0720 MHz */ | ||
540 | .filter = WMC_SR_12KHZ, | ||
541 | }, | ||
542 | [HW_FREQ_16] = /* PLL = 65.536MHz */ | ||
543 | { | ||
544 | .plln = 7 | WMC_PLL_PRESCALE, | ||
545 | .pllk1 = 0x2f, /* 12414886 */ | ||
546 | .pllk2 = 0x0b7, | ||
547 | .pllk3 = 0x1a6, | ||
548 | .mclkdiv = WMC_MCLKDIV_4, /* 4.0960 MHz */ | ||
549 | .filter = WMC_SR_16KHZ, | ||
550 | }, | ||
551 | [HW_FREQ_22] = /* PLL = off */ | ||
552 | { | ||
553 | .mclkdiv = WMC_MCLKDIV_3, /* 5.6448 MHz */ | ||
554 | .filter = WMC_SR_24KHZ, | ||
555 | }, | ||
556 | [HW_FREQ_24] = /* PLL = 73.728 MHz */ | ||
557 | { | ||
558 | .plln = 8 | WMC_PLL_PRESCALE, | ||
559 | .pllk1 = 0x2d, /* 11869595 */ | ||
560 | .pllk2 = 0x08e, | ||
561 | .pllk3 = 0x19b, | ||
562 | .mclkdiv = WMC_MCLKDIV_3, /* 6.1440 MHz */ | ||
563 | .filter = WMC_SR_24KHZ, | ||
564 | }, | ||
565 | [HW_FREQ_32] = /* PLL = 65.536MHz */ | ||
566 | { | ||
567 | .plln = 7 | WMC_PLL_PRESCALE, | ||
568 | .pllk1 = 0x2f, /* 12414886 */ | ||
569 | .pllk2 = 0x0b7, | ||
570 | .pllk3 = 0x1a6, | ||
571 | .mclkdiv = WMC_MCLKDIV_2, /* 8.1920 MHz */ | ||
572 | .filter = WMC_SR_32KHZ, | ||
573 | }, | ||
574 | [HW_FREQ_44] = /* PLL = off */ | ||
575 | { | ||
576 | .mclkdiv = WMC_MCLKDIV_1_5, /* 11.2896 MHz */ | ||
577 | .filter = WMC_SR_48KHZ, | ||
578 | }, | ||
579 | [HW_FREQ_48] = /* PLL = 73.728 MHz */ | ||
580 | { | ||
581 | .plln = 8 | WMC_PLL_PRESCALE, | ||
582 | .pllk1 = 0x2d, /* 11869595 */ | ||
583 | .pllk2 = 0x08e, | ||
584 | .pllk3 = 0x19b, | ||
585 | .mclkdiv = WMC_MCLKDIV_1_5, /* 12.2880 MHz */ | ||
586 | .filter = WMC_SR_48KHZ, | ||
587 | }, | ||
588 | }; | ||
589 | |||
590 | unsigned int plln; | 509 | unsigned int plln; |
591 | unsigned int mclkdiv; | 510 | unsigned int mclkdiv; |
592 | 511 | ||
@@ -594,10 +513,10 @@ void audiohw_set_frequency(int fsel) | |||
594 | fsel = HW_FREQ_DEFAULT; | 513 | fsel = HW_FREQ_DEFAULT; |
595 | 514 | ||
596 | /* Setup filters. */ | 515 | /* Setup filters. */ |
597 | wmc_write(WMC_ADDITIONAL_CTRL, srctrl_table[fsel].filter); | 516 | wmc_write(WMC_ADDITIONAL_CTRL, wmc_srctrl_table[fsel].filter); |
598 | 517 | ||
599 | plln = srctrl_table[fsel].plln; | 518 | plln = wmc_srctrl_table[fsel].plln; |
600 | mclkdiv = srctrl_table[fsel].mclkdiv; | 519 | mclkdiv = wmc_srctrl_table[fsel].mclkdiv; |
601 | 520 | ||
602 | if (plln != 0) | 521 | if (plln != 0) |
603 | { | 522 | { |
@@ -605,9 +524,9 @@ void audiohw_set_frequency(int fsel) | |||
605 | 524 | ||
606 | /* Program PLL. */ | 525 | /* Program PLL. */ |
607 | wmc_write(WMC_PLL_N, plln); | 526 | wmc_write(WMC_PLL_N, plln); |
608 | wmc_write(WMC_PLL_K1, srctrl_table[fsel].pllk1); | 527 | wmc_write(WMC_PLL_K1, wmc_srctrl_table[fsel].pllk1); |
609 | wmc_write(WMC_PLL_K2, srctrl_table[fsel].pllk2); | 528 | wmc_write(WMC_PLL_K2, wmc_srctrl_table[fsel].pllk2); |
610 | wmc_write(WMC_PLL_K3, srctrl_table[fsel].pllk3); | 529 | wmc_write(WMC_PLL_K3, wmc_srctrl_table[fsel].pllk3); |
611 | 530 | ||
612 | /* Turn on PLL. */ | 531 | /* Turn on PLL. */ |
613 | wmc_set(WMC_POWER_MANAGEMENT1, WMC_PLLEN); | 532 | wmc_set(WMC_POWER_MANAGEMENT1, WMC_PLLEN); |
diff --git a/firmware/export/wm8978.h b/firmware/export/wm8978.h index 4081d05a89..f591c1b9fb 100644 --- a/firmware/export/wm8978.h +++ b/firmware/export/wm8978.h | |||
@@ -499,4 +499,15 @@ void wmc_clear(unsigned int reg, unsigned int bits); | |||
499 | #define WMC_RMIX2OUT4 (1 << 1) | 499 | #define WMC_RMIX2OUT4 (1 << 1) |
500 | #define WMC_RDAC2OUT4 (1 << 0) | 500 | #define WMC_RDAC2OUT4 (1 << 0) |
501 | 501 | ||
502 | /* For implementing samplerate conrol */ | ||
503 | struct wmc_srctrl_entry | ||
504 | { | ||
505 | uint32_t plln : 8; | ||
506 | uint32_t pllk1 : 6; | ||
507 | uint32_t pllk2 : 9; | ||
508 | uint32_t pllk3 : 9; | ||
509 | unsigned char mclkdiv; | ||
510 | unsigned char filter; | ||
511 | }; | ||
512 | |||
502 | #endif /* _WM8978_H */ | 513 | #endif /* _WM8978_H */ |
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 | } |
diff --git a/firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c index 65571a4ee2..1c21415752 100644 --- a/firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c +++ b/firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c | |||
@@ -23,7 +23,7 @@ | |||
23 | #include "kernel.h" | 23 | #include "kernel.h" |
24 | #include "audio.h" | 24 | #include "audio.h" |
25 | #include "sound.h" | 25 | #include "sound.h" |
26 | #include "ccm-imx31.h" | 26 | //#include "ccm-imx31.h" |
27 | #include "sdma-imx31.h" | 27 | #include "sdma-imx31.h" |
28 | #include "mmu-imx31.h" | 28 | #include "mmu-imx31.h" |
29 | #include "pcm-internal.h" | 29 | #include "pcm-internal.h" |
@@ -149,101 +149,11 @@ void pcm_dma_apply_settings(void) | |||
149 | 149 | ||
150 | void pcm_play_dma_init(void) | 150 | void pcm_play_dma_init(void) |
151 | { | 151 | { |
152 | /* Init channel information */ | 152 | /* Init DMA channel information */ |
153 | sdma_channel_init(DMA_PLAY_CH_NUM, &dma_play_cd, &dma_play_bd); | 153 | sdma_channel_init(DMA_PLAY_CH_NUM, &dma_play_cd, &dma_play_bd); |
154 | sdma_channel_set_priority(DMA_PLAY_CH_NUM, DMA_PLAY_CH_PRIORITY); | 154 | sdma_channel_set_priority(DMA_PLAY_CH_NUM, DMA_PLAY_CH_PRIORITY); |
155 | 155 | ||
156 | ccm_module_clock_gating(CG_SSI1, CGM_ON_RUN_WAIT); | 156 | /* Init audio interfaces */ |
157 | ccm_module_clock_gating(CG_SSI2, CGM_ON_RUN_WAIT); | ||
158 | |||
159 | /* Reset & disable SSIs */ | ||
160 | SSI_SCR1 &= ~SSI_SCR_SSIEN; | ||
161 | SSI_SCR2 &= ~SSI_SCR_SSIEN; | ||
162 | |||
163 | SSI_SIER1 = 0; | ||
164 | SSI_SIER2 = 0; | ||
165 | |||
166 | /* Set up audio mux */ | ||
167 | |||
168 | /* Port 2 (internally connected to SSI2) | ||
169 | * All clocking is output sourced from port 4 */ | ||
170 | AUDMUX_PTCR2 = AUDMUX_PTCR_TFS_DIR | AUDMUX_PTCR_TFSEL_PORT4 | | ||
171 | AUDMUX_PTCR_TCLKDIR | AUDMUX_PTCR_TCSEL_PORT4 | | ||
172 | AUDMUX_PTCR_SYN; | ||
173 | |||
174 | /* Receive data from port 4 */ | ||
175 | AUDMUX_PDCR2 = AUDMUX_PDCR_RXDSEL_PORT4; | ||
176 | /* All clock lines are inputs sourced from the master mode codec and | ||
177 | * sent back to SSI2 through port 2 */ | ||
178 | AUDMUX_PTCR4 = AUDMUX_PTCR_SYN; | ||
179 | |||
180 | /* Receive data from port 2 */ | ||
181 | AUDMUX_PDCR4 = AUDMUX_PDCR_RXDSEL_PORT2; | ||
182 | |||
183 | /* PORT1 (internally connected to SSI1) routes clocking to PORT5 to | ||
184 | * provide MCLK to the codec */ | ||
185 | /* TX clocks are inputs taken from SSI2 */ | ||
186 | /* RX clocks are outputs taken from PORT4 */ | ||
187 | AUDMUX_PTCR1 = AUDMUX_PTCR_RFS_DIR | AUDMUX_PTCR_RFSSEL_PORT4 | | ||
188 | AUDMUX_PTCR_RCLKDIR | AUDMUX_PTCR_RCSEL_PORT4; | ||
189 | /* RX data taken from PORT4 */ | ||
190 | AUDMUX_PDCR1 = AUDMUX_PDCR_RXDSEL_PORT4; | ||
191 | |||
192 | /* PORT5 outputs TCLK sourced from PORT1 (SSI1) */ | ||
193 | AUDMUX_PTCR5 = AUDMUX_PTCR_TCLKDIR | AUDMUX_PTCR_TCSEL_PORT1; | ||
194 | AUDMUX_PDCR5 = 0; | ||
195 | |||
196 | /* Setup SSIs */ | ||
197 | |||
198 | /* SSI2 - SoC software interface for all I2S data out */ | ||
199 | SSI_SCR2 = SSI_SCR_SYN | SSI_SCR_I2S_MODE_SLAVE; | ||
200 | SSI_STCR2 = SSI_STCR_TXBIT0 | SSI_STCR_TSCKP | SSI_STCR_TFSI | | ||
201 | SSI_STCR_TEFS | SSI_STCR_TFEN0; | ||
202 | |||
203 | /* 16 bits per word, 2 words per frame */ | ||
204 | SSI_STCCR2 = SSI_STRCCR_WL16 | ((2-1) << SSI_STRCCR_DC_POS) | | ||
205 | ((4-1) << SSI_STRCCR_PM_POS); | ||
206 | |||
207 | /* Transmit low watermark */ | ||
208 | SSI_SFCSR2 = (SSI_SFCSR2 & ~SSI_SFCSR_TFWM0) | | ||
209 | ((8-SDMA_SSI_TXFIFO_WML) << SSI_SFCSR_TFWM0_POS); | ||
210 | SSI_STMSK2 = 0; | ||
211 | |||
212 | /* SSI1 - provides MCLK to codec. Receives data from codec. */ | ||
213 | SSI_STCR1 = SSI_STCR_TXDIR; | ||
214 | |||
215 | /* f(INT_BIT_CLK) = | ||
216 | * f(SYS_CLK) / [(DIV2 + 1)*(7*PSR + 1)*(PM + 1)*2] = | ||
217 | * 677737600 / [(1 + 1)*(7*0 + 1)*(0 + 1)*2] = | ||
218 | * 677737600 / 4 = 169344000 Hz | ||
219 | * | ||
220 | * 45.4.2.2 DIV2, PSR, and PM Bit Description states: | ||
221 | * Bits DIV2, PSR, and PM should not be all set to zero at the same | ||
222 | * time. | ||
223 | * | ||
224 | * The hardware seems to force a divide by 4 even if all bits are | ||
225 | * zero but comply by setting DIV2 and the others to zero. | ||
226 | */ | ||
227 | SSI_STCCR1 = SSI_STRCCR_DIV2 | ((1-1) << SSI_STRCCR_PM_POS); | ||
228 | |||
229 | /* SSI1 - receive - asynchronous clocks */ | ||
230 | SSI_SCR1 = SSI_SCR_I2S_MODE_SLAVE; | ||
231 | |||
232 | SSI_SRCR1 = SSI_SRCR_RXBIT0 | SSI_SRCR_RSCKP | SSI_SRCR_RFSI | | ||
233 | SSI_SRCR_REFS; | ||
234 | |||
235 | /* 16 bits per word, 2 words per frame */ | ||
236 | SSI_SRCCR1 = SSI_STRCCR_WL16 | ((2-1) << SSI_STRCCR_DC_POS) | | ||
237 | ((4-1) << SSI_STRCCR_PM_POS); | ||
238 | |||
239 | /* Receive high watermark */ | ||
240 | SSI_SFCSR1 = (SSI_SFCSR1 & ~SSI_SFCSR_RFWM0) | | ||
241 | (SDMA_SSI_RXFIFO_WML << SSI_SFCSR_RFWM0_POS); | ||
242 | SSI_SRMSK1 = 0; | ||
243 | |||
244 | /* Enable SSI1 (codec clock) */ | ||
245 | SSI_SCR1 |= SSI_SCR_SSIEN; | ||
246 | |||
247 | audiohw_init(); | 157 | audiohw_init(); |
248 | } | 158 | } |
249 | 159 | ||
diff --git a/firmware/target/arm/imx31/gigabeat-s/wmcodec-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/wmcodec-gigabeat-s.c index 36ab33a5dc..ca23aa4e56 100644 --- a/firmware/target/arm/imx31/gigabeat-s/wmcodec-gigabeat-s.c +++ b/firmware/target/arm/imx31/gigabeat-s/wmcodec-gigabeat-s.c | |||
@@ -22,24 +22,93 @@ | |||
22 | ****************************************************************************/ | 22 | ****************************************************************************/ |
23 | #include "config.h" | 23 | #include "config.h" |
24 | #include "system.h" | 24 | #include "system.h" |
25 | #include "kernel.h" | 25 | #include "audiohw.h" |
26 | #include "sound.h" | ||
27 | #include "wmcodec.h" | 26 | #include "wmcodec.h" |
27 | #include "audio.h" | ||
28 | #include "i2s.h" | 28 | #include "i2s.h" |
29 | #include "i2c-imx31.h" | 29 | #include "i2c-imx31.h" |
30 | 30 | ||
31 | /* NOTE: Some port-specific bits will have to be moved away (node and GPIO | ||
32 | * writes) for cleanest implementation. */ | ||
33 | |||
34 | static struct i2c_node wm8978_i2c_node = | 31 | static struct i2c_node wm8978_i2c_node = |
35 | { | 32 | { |
36 | .num = I2C1_NUM, | 33 | .num = I2C1_NUM, |
37 | .ifdr = I2C_IFDR_DIV192, /* 66MHz/.4MHz = 165, closest = 192 = 343750Hz */ | 34 | .ifdr = I2C_IFDR_DIV192, /* 66MHz/.4MHz = 165, closest = 192 = 343750Hz */ |
38 | /* Just hard-code for now - scaling may require | ||
39 | * updating */ | ||
40 | .addr = WMC_I2C_ADDR, | 35 | .addr = WMC_I2C_ADDR, |
41 | }; | 36 | }; |
42 | 37 | ||
38 | /* For 16.9344MHz MCLK, codec as master. */ | ||
39 | const struct wmc_srctrl_entry wmc_srctrl_table[HW_NUM_FREQ] = | ||
40 | { | ||
41 | [HW_FREQ_8] = /* PLL = 65.536MHz */ | ||
42 | { | ||
43 | .plln = 7 | WMC_PLL_PRESCALE, | ||
44 | .pllk1 = 0x2f, /* 12414886 */ | ||
45 | .pllk2 = 0x0b7, | ||
46 | .pllk3 = 0x1a6, | ||
47 | .mclkdiv = WMC_MCLKDIV_8, /* 2.0480 MHz */ | ||
48 | .filter = WMC_SR_8KHZ, | ||
49 | }, | ||
50 | [HW_FREQ_11] = /* PLL = off */ | ||
51 | { | ||
52 | .mclkdiv = WMC_MCLKDIV_6, /* 2.8224 MHz */ | ||
53 | .filter = WMC_SR_12KHZ, | ||
54 | }, | ||
55 | [HW_FREQ_12] = /* PLL = 73.728 MHz */ | ||
56 | { | ||
57 | .plln = 8 | WMC_PLL_PRESCALE, | ||
58 | .pllk1 = 0x2d, /* 11869595 */ | ||
59 | .pllk2 = 0x08e, | ||
60 | .pllk3 = 0x19b, | ||
61 | .mclkdiv = WMC_MCLKDIV_6, /* 3.0720 MHz */ | ||
62 | .filter = WMC_SR_12KHZ, | ||
63 | }, | ||
64 | [HW_FREQ_16] = /* PLL = 65.536MHz */ | ||
65 | { | ||
66 | .plln = 7 | WMC_PLL_PRESCALE, | ||
67 | .pllk1 = 0x2f, /* 12414886 */ | ||
68 | .pllk2 = 0x0b7, | ||
69 | .pllk3 = 0x1a6, | ||
70 | .mclkdiv = WMC_MCLKDIV_4, /* 4.0960 MHz */ | ||
71 | .filter = WMC_SR_16KHZ, | ||
72 | }, | ||
73 | [HW_FREQ_22] = /* PLL = off */ | ||
74 | { | ||
75 | .mclkdiv = WMC_MCLKDIV_3, /* 5.6448 MHz */ | ||
76 | .filter = WMC_SR_24KHZ, | ||
77 | }, | ||
78 | [HW_FREQ_24] = /* PLL = 73.728 MHz */ | ||
79 | { | ||
80 | .plln = 8 | WMC_PLL_PRESCALE, | ||
81 | .pllk1 = 0x2d, /* 11869595 */ | ||
82 | .pllk2 = 0x08e, | ||
83 | .pllk3 = 0x19b, | ||
84 | .mclkdiv = WMC_MCLKDIV_3, /* 6.1440 MHz */ | ||
85 | .filter = WMC_SR_24KHZ, | ||
86 | }, | ||
87 | [HW_FREQ_32] = /* PLL = 65.536MHz */ | ||
88 | { | ||
89 | .plln = 7 | WMC_PLL_PRESCALE, | ||
90 | .pllk1 = 0x2f, /* 12414886 */ | ||
91 | .pllk2 = 0x0b7, | ||
92 | .pllk3 = 0x1a6, | ||
93 | .mclkdiv = WMC_MCLKDIV_2, /* 8.1920 MHz */ | ||
94 | .filter = WMC_SR_32KHZ, | ||
95 | }, | ||
96 | [HW_FREQ_44] = /* PLL = off */ | ||
97 | { | ||
98 | .mclkdiv = WMC_MCLKDIV_1_5, /* 11.2896 MHz */ | ||
99 | .filter = WMC_SR_48KHZ, | ||
100 | }, | ||
101 | [HW_FREQ_48] = /* PLL = 73.728 MHz */ | ||
102 | { | ||
103 | .plln = 8 | WMC_PLL_PRESCALE, | ||
104 | .pllk1 = 0x2d, /* 11869595 */ | ||
105 | .pllk2 = 0x08e, | ||
106 | .pllk3 = 0x19b, | ||
107 | .mclkdiv = WMC_MCLKDIV_1_5, /* 12.2880 MHz */ | ||
108 | .filter = WMC_SR_48KHZ, | ||
109 | }, | ||
110 | }; | ||
111 | |||
43 | void audiohw_init(void) | 112 | void audiohw_init(void) |
44 | { | 113 | { |
45 | i2s_reset(); | 114 | i2s_reset(); |