summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcoen Hirschberg <marcoen@gmail.com>2006-10-20 17:12:42 +0000
committerMarcoen Hirschberg <marcoen@gmail.com>2006-10-20 17:12:42 +0000
commit1d7ebdfe268b7c1ff7aeb187491dee5ae1940208 (patch)
tree4caca06ae35448cd1a10b0d55bde5c1a2f626da1
parent167a9364a085794764836bd3017ae4e88ddb3500 (diff)
downloadrockbox-1d7ebdfe268b7c1ff7aeb187491dee5ae1940208.tar.gz
rockbox-1d7ebdfe268b7c1ff7aeb187491dee5ae1940208.zip
generalise the wolfson codec code a bit
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11277 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/SOURCES15
-rw-r--r--firmware/drivers/wm8731l.c153
-rw-r--r--firmware/drivers/wm8758.c128
-rw-r--r--firmware/drivers/wm8975.c122
-rw-r--r--firmware/export/wmcodec.h23
-rw-r--r--firmware/target/arm/gigabeat/meg-fx/wmcodec-meg-fx.c61
-rw-r--r--firmware/target/arm/wmcodec-pp.c156
7 files changed, 337 insertions, 321 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 62e1fd0853..3c293492f4 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -199,7 +199,7 @@ descramble.S
199#endif 199#endif
200#if defined(HAVE_UDA1380) && !defined(SIMULATOR) 200#if defined(HAVE_UDA1380) && !defined(SIMULATOR)
201drivers/uda1380.c 201drivers/uda1380.c
202#elif defined(HAVE_WM8975) && !defined(SIMULATOR) 202#elif (defined(HAVE_WM8975) || defined(HAVE_WM8751)) && !defined(SIMULATOR)
203drivers/wm8975.c 203drivers/wm8975.c
204#elif defined(HAVE_WM8758) && !defined(SIMULATOR) 204#elif defined(HAVE_WM8758) && !defined(SIMULATOR)
205drivers/wm8758.c 205drivers/wm8758.c
@@ -233,6 +233,7 @@ drivers/m5636.c
233target/arm/sandisk/sansa-e200/ata-e200.c 233target/arm/sandisk/sansa-e200/ata-e200.c
234target/arm/sandisk/sansa-e200/lcd-e200.c 234target/arm/sandisk/sansa-e200/lcd-e200.c
235target/arm/sandisk/sansa-e200/adc-e200.c 235target/arm/sandisk/sansa-e200/adc-e200.c
236target/arm/wmcodec-pp.c
236#endif 237#endif
237 238
238#ifdef IAUDIO_X5 239#ifdef IAUDIO_X5
@@ -268,6 +269,7 @@ target/arm/iriver/h10/power-h10.c
268target/arm/iriver/h10/usb-h10.c 269target/arm/iriver/h10/usb-h10.c
269target/arm/iriver/h10/lcd-h10_20gb.c 270target/arm/iriver/h10/lcd-h10_20gb.c
270target/arm/iriver/h10/adc-h10.c 271target/arm/iriver/h10/adc-h10.c
272target/arm/wmcodec-pp.c
271#endif 273#endif
272#endif 274#endif
273 275
@@ -280,6 +282,7 @@ target/arm/iriver/h10/power-h10.c
280target/arm/iriver/h10/usb-h10.c 282target/arm/iriver/h10/usb-h10.c
281target/arm/iriver/h10/lcd-h10_5gb.c 283target/arm/iriver/h10/lcd-h10_5gb.c
282target/arm/iriver/h10/adc-h10.c 284target/arm/iriver/h10/adc-h10.c
285target/arm/wmcodec-pp.c
283#endif 286#endif
284#endif 287#endif
285 288
@@ -295,6 +298,8 @@ target/arm/gigabeat/meg-fx/sc606-meg-fx.c
295target/arm/gigabeat/meg-fx/adc-meg-fx.c 298target/arm/gigabeat/meg-fx/adc-meg-fx.c
296drivers/generic_i2c.c 299drivers/generic_i2c.c
297target/arm/gigabeat/meg-fx/i2c-meg-fx.c 300target/arm/gigabeat/meg-fx/i2c-meg-fx.c
301target/arm/gigabeat/meg-fx/mmu-meg-fx.c
302target/arm/gigabeat/meg-fx/wmcodec-meg-fx.c
298#endif 303#endif
299#endif 304#endif
300 305
@@ -307,6 +312,7 @@ target/arm/tatung/tpj1022/power-tpj1022.c
307target/arm/tatung/tpj1022/usb-tpj1022.c 312target/arm/tatung/tpj1022/usb-tpj1022.c
308target/arm/tatung/tpj1022/lcd-tpj1022.c 313target/arm/tatung/tpj1022/lcd-tpj1022.c
309target/arm/tatung/tpj1022/adc-tpj1022.c 314target/arm/tatung/tpj1022/adc-tpj1022.c
315target/arm/wmcodec-pp.c
310#endif 316#endif
311#endif 317#endif
312 318
@@ -320,6 +326,7 @@ target/arm/ipod/backlight-4g_color.c
320target/arm/ipod/button-clickwheel.c 326target/arm/ipod/button-clickwheel.c
321target/arm/ipod/power-ipod.c 327target/arm/ipod/power-ipod.c
322target/arm/ipod/usb-ipod.c 328target/arm/ipod/usb-ipod.c
329target/arm/wmcodec-pp.c
323#endif 330#endif
324#endif 331#endif
325 332
@@ -333,6 +340,7 @@ target/arm/ipod/backlight-4g_color.c
333target/arm/ipod/button-clickwheel.c 340target/arm/ipod/button-clickwheel.c
334target/arm/ipod/power-ipod.c 341target/arm/ipod/power-ipod.c
335target/arm/ipod/usb-ipod.c 342target/arm/ipod/usb-ipod.c
343target/arm/wmcodec-pp.c
336#endif 344#endif
337#endif 345#endif
338 346
@@ -346,6 +354,7 @@ target/arm/ipod/backlight-nano_video.c
346target/arm/ipod/button-clickwheel.c 354target/arm/ipod/button-clickwheel.c
347target/arm/ipod/power-ipod.c 355target/arm/ipod/power-ipod.c
348target/arm/ipod/usb-ipod.c 356target/arm/ipod/usb-ipod.c
357target/arm/wmcodec-pp.c
349#endif 358#endif
350#endif 359#endif
351 360
@@ -359,6 +368,7 @@ target/arm/ipod/button-clickwheel.c
359target/arm/ipod/power-ipod.c 368target/arm/ipod/power-ipod.c
360target/arm/ipod/usb-ipod.c 369target/arm/ipod/usb-ipod.c
361drivers/lcd-ipodvideo.c 370drivers/lcd-ipodvideo.c
371target/arm/wmcodec-pp.c
362#endif 372#endif
363#endif 373#endif
364 374
@@ -372,6 +382,7 @@ target/arm/ipod/3g/backlight-3g.c
372target/arm/ipod/3g/button-3g.c 382target/arm/ipod/3g/button-3g.c
373target/arm/ipod/power-ipod.c 383target/arm/ipod/power-ipod.c
374target/arm/ipod/usb-ipod.c 384target/arm/ipod/usb-ipod.c
385target/arm/wmcodec-pp.c
375#endif 386#endif
376#endif 387#endif
377 388
@@ -385,6 +396,7 @@ target/arm/ipod/backlight-mini1g_mini2g.c
385target/arm/ipod/button-mini1g.c 396target/arm/ipod/button-mini1g.c
386target/arm/ipod/power-ipod.c 397target/arm/ipod/power-ipod.c
387target/arm/ipod/usb-ipod.c 398target/arm/ipod/usb-ipod.c
399target/arm/wmcodec-pp.c
388#endif 400#endif
389#endif 401#endif
390 402
@@ -399,5 +411,6 @@ target/arm/ipod/backlight-mini1g_mini2g.c
399target/arm/ipod/button-clickwheel.c 411target/arm/ipod/button-clickwheel.c
400target/arm/ipod/power-ipod.c 412target/arm/ipod/power-ipod.c
401target/arm/ipod/usb-ipod.c 413target/arm/ipod/usb-ipod.c
414target/arm/wmcodec-pp.c
402#endif 415#endif
403#endif 416#endif
diff --git a/firmware/drivers/wm8731l.c b/firmware/drivers/wm8731l.c
index 71ccfdb4f6..be9bf14099 100644
--- a/firmware/drivers/wm8731l.c
+++ b/firmware/drivers/wm8731l.c
@@ -37,34 +37,21 @@
37#include "buffer.h" 37#include "buffer.h"
38#include "audio.h" 38#include "audio.h"
39 39
40#include "i2c-pp5002.h" 40#include "wmcodec.h"
41#include "wm8731l.h" 41#include "wm8731l.h"
42#include "pcf50605.h"
43 42
44#define IPOD_PCM_LEVEL 0x65 /* -6dB */ 43#define IPOD_PCM_LEVEL 0x65 /* -6dB */
45 44
46void wm8731_write(int reg, int data)
47{
48/* Todo: Since the ipod_i2c_* functions also work on H10 and possibly other PP
49 targets, these functions should probably be renamed */
50#if defined(IRIVER_H10) || defined(IRIVER_H10_5GB)
51 /* The H10's audio codec uses an I2C address of 0x1b */
52 ipod_i2c_send(0x1b, (reg<<1) | ((data&0x100)>>8),data&0xff);
53#else
54 /* The iPod's audio codecs use an I2C address of 0x1a */
55 ipod_i2c_send(0x1a, (reg<<1) | ((data&0x100)>>8),data&0xff);
56#endif
57}
58 45
59int wmcodec_mute(int mute) 46int wmcodec_mute(int mute)
60{ 47{
61 if (mute) 48 if (mute)
62 { 49 {
63 /* Set DACMU = 1 to soft-mute the audio DACs. */ 50 /* Set DACMU = 1 to soft-mute the audio DACs. */
64 wm8731_write(DACCTRL, 0x8); 51 wmcodec_write(DACCTRL, 0x8);
65 } else { 52 } else {
66 /* Set DACMU = 0 to soft-un-mute the audio DACs. */ 53 /* Set DACMU = 0 to soft-un-mute the audio DACs. */
67 wm8731_write(DACCTRL, 0x0); 54 wmcodec_write(DACCTRL, 0x0);
68 } 55 }
69 56
70 return 0; 57 return 0;
@@ -75,110 +62,12 @@ static void codec_set_active(int active)
75{ 62{
76 /* set active to 0x0 or 0x1 */ 63 /* set active to 0x0 or 0x1 */
77 if (active) { 64 if (active) {
78 wm8731_write(ACTIVECTRL, 0x01); 65 wmcodec_write(ACTIVECTRL, 0x01);
79 } else { 66 } else {
80 wm8731_write(ACTIVECTRL, 0x00); 67 wmcodec_write(ACTIVECTRL, 0x00);
81 } 68 }
82} 69}
83 70
84/*
85 * Reset the I2S BIT.FORMAT I2S, 16bit, FIFO.FORMAT 32bit
86 */
87static void i2s_reset(void)
88{
89#if CONFIG_CPU == PP5020
90 /* I2S soft reset */
91 outl(inl(0x70002800) | 0x80000000, 0x70002800);
92 outl(inl(0x70002800) & ~0x80000000, 0x70002800);
93
94 /* BIT.FORMAT [11:10] = I2S (default) */
95 outl(inl(0x70002800) & ~0xc00, 0x70002800);
96 /* BIT.SIZE [9:8] = 16bit (default) */
97 outl(inl(0x70002800) & ~0x300, 0x70002800);
98
99 /* FIFO.FORMAT [6:4] = 32 bit LSB */
100 /* since BIT.SIZ < FIFO.FORMAT low 16 bits will be 0 */
101 outl(inl(0x70002800) | 0x30, 0x70002800);
102
103 /* RX_ATN_LVL=1 == when 12 slots full */
104 /* TX_ATN_LVL=1 == when 12 slots empty */
105 outl(inl(0x7000280c) | 0x33, 0x7000280c);
106
107 /* Rx.CLR = 1, TX.CLR = 1 */
108 outl(inl(0x7000280c) | 0x1100, 0x7000280c);
109#elif CONFIG_CPU == PP5002
110 /* I2S device reset */
111 outl(inl(0xcf005030) | 0x80, 0xcf005030);
112 outl(inl(0xcf005030) & ~0x80, 0xcf005030);
113
114 /* I2S controller enable */
115 outl(inl(0xc0002500) | 0x1, 0xc0002500);
116
117 /* BIT.FORMAT [11:10] = I2S (default) */
118 /* BIT.SIZE [9:8] = 24bit */
119 /* FIFO.FORMAT = 24 bit LSB */
120
121 /* reset DAC and ADC fifo */
122 outl(inl(0xc000251c) | 0x30000, 0xc000251c);
123#endif
124}
125
126/*
127 * Initialise the WM8975 for playback via headphone and line out.
128 * Note, I'm using the WM8750 datasheet as its apparently close.
129 */
130int wmcodec_init(void) {
131 /* reset I2C */
132 i2c_init();
133
134#if CONFIG_CPU == PP5020
135 /* normal outputs for CDI and I2S pin groups */
136 outl(inl(0x70000020) & ~0x300, 0x70000020);
137
138 /*mini2?*/
139 outl(inl(0x70000010) & ~0x3000000, 0x70000010);
140 /*mini2?*/
141
142 /* device reset */
143 outl(inl(0x60006004) | 0x800, 0x60006004);
144 outl(inl(0x60006004) & ~0x800, 0x60006004);
145
146 /* device enable */
147 outl(inl(0x6000600C) | 0x807, 0x6000600C);
148
149 /* enable external dev clock clocks */
150 outl(inl(0x6000600c) | 0x2, 0x6000600c);
151
152 /* external dev clock to 24MHz */
153 outl(inl(0x70000018) & ~0xc, 0x70000018);
154#else
155 /* device reset */
156 outl(inl(0xcf005030) | 0x80, 0xcf005030);
157 outl(inl(0xcf005030) & ~0x80, 0xcf005030);
158
159 /* device enable */
160 outl(inl(0xcf005000) | 0x80, 0xcf005000);
161
162 /* GPIO D06 enable for output */
163 outl(inl(0xcf00000c) | 0x40, 0xcf00000c);
164 outl(inl(0xcf00001c) & ~0x40, 0xcf00001c);
165 /* bits 11,10 == 01 */
166 outl(inl(0xcf004040) | 0x400, 0xcf004040);
167 outl(inl(0xcf004040) & ~0x800, 0xcf004040);
168
169 outl(inl(0xcf004048) & ~0x1, 0xcf004048);
170
171 outl(inl(0xcf000004) & ~0xf, 0xcf000004);
172 outl(inl(0xcf004044) & ~0xf, 0xcf004044);
173
174 /* C03 = 0 */
175 outl(inl(0xcf000008) | 0x8, 0xcf000008);
176 outl(inl(0xcf000018) | 0x8, 0xcf000018);
177 outl(inl(0xcf000028) & ~0x8, 0xcf000028);
178#endif
179
180 return 0;
181}
182 71
183/* Silently enable / disable audio output */ 72/* Silently enable / disable audio output */
184void wmcodec_enable_output(bool enable) 73void wmcodec_enable_output(bool enable)
@@ -188,36 +77,36 @@ void wmcodec_enable_output(bool enable)
188 /* reset the I2S controller into known state */ 77 /* reset the I2S controller into known state */
189 i2s_reset(); 78 i2s_reset();
190 79
191 wm8731_write(RESET, 0x0); /*Reset*/ 80 wmcodec_write(RESET, 0x0); /*Reset*/
192 81
193 codec_set_active(0x0); 82 codec_set_active(0x0);
194 83
195#ifdef HAVE_WM8721 84#ifdef HAVE_WM8721
196 /* DACSEL=1 */ 85 /* DACSEL=1 */
197 wm8731_write(0x4, 0x10); 86 wmcodec_write(0x4, 0x10);
198#elif defined HAVE_WM8731 87#elif defined HAVE_WM8731
199 /* DACSEL=1, BYPASS=1 */ 88 /* DACSEL=1, BYPASS=1 */
200 wm8731_write(0x4, 0x18); 89 wmcodec_write(0x4, 0x18);
201#endif 90#endif
202 91
203 /* set power register to POWEROFF=0 on OUTPD=0, DACPD=0 */ 92 /* set power register to POWEROFF=0 on OUTPD=0, DACPD=0 */
204 wm8731_write(PWRMGMT, 0x67); 93 wmcodec_write(PWRMGMT, 0x67);
205 94
206 /* BCLKINV=0(Dont invert BCLK) MS=1(Enable Master) LRSWAP=0 LRP=0 */ 95 /* BCLKINV=0(Dont invert BCLK) MS=1(Enable Master) LRSWAP=0 LRP=0 */
207 /* IWL=00(16 bit) FORMAT=10(I2S format) */ 96 /* IWL=00(16 bit) FORMAT=10(I2S format) */
208 wm8731_write(AINTFCE, 0x42); 97 wmcodec_write(AINTFCE, 0x42);
209 98
210 wmcodec_set_sample_rate(WM8731L_44100HZ); 99 wmcodec_set_sample_rate(WM8731L_44100HZ);
211 100
212 /* set the volume to -6dB */ 101 /* set the volume to -6dB */
213 wm8731_write(LOUTVOL, IPOD_PCM_LEVEL); 102 wmcodec_write(LOUTVOL, IPOD_PCM_LEVEL);
214 wm8731_write(ROUTVOL, 0x100 | IPOD_PCM_LEVEL); 103 wmcodec_write(ROUTVOL, 0x100 | IPOD_PCM_LEVEL);
215 104
216 /* ACTIVE=1 */ 105 /* ACTIVE=1 */
217 codec_set_active(1); 106 codec_set_active(1);
218 107
219 /* 5. Set DACMU = 0 to soft-un-mute the audio DACs. */ 108 /* 5. Set DACMU = 0 to soft-un-mute the audio DACs. */
220 wm8731_write(DACCTRL, 0x0); 109 wmcodec_write(DACCTRL, 0x0);
221 110
222#if defined(IRIVER_H10) || defined(IRIVER_H10_5GB) 111#if defined(IRIVER_H10) || defined(IRIVER_H10_5GB)
223 /* We need to enable bit 4 of GPIOL for output for sound on H10 */ 112 /* We need to enable bit 4 of GPIOL for output for sound on H10 */
@@ -241,8 +130,8 @@ int wmcodec_set_master_vol(int vol_l, int vol_r)
241 /* 0110000 == -73dB */ 130 /* 0110000 == -73dB */
242 /* 0101111 == mute (0x2f) */ 131 /* 0101111 == mute (0x2f) */
243 132
244 wm8731_write(LOUTVOL, vol_l); 133 wmcodec_write(LOUTVOL, vol_l);
245 wm8731_write(ROUTVOL, vol_r); 134 wmcodec_write(ROUTVOL, vol_r);
246 135
247 return 0; 136 return 0;
248} 137}
@@ -269,22 +158,22 @@ void wmcodec_set_treble(int value)
269void wmcodec_close(void) 158void wmcodec_close(void)
270{ 159{
271 /* set DACMU=1 DEEMPH=0 */ 160 /* set DACMU=1 DEEMPH=0 */
272 wm8731_write(DACCTRL, 0x8); 161 wmcodec_write(DACCTRL, 0x8);
273 162
274 /* ACTIVE=0 */ 163 /* ACTIVE=0 */
275 codec_set_active(0x0); 164 codec_set_active(0x0);
276 165
277 /* line in mute left & right*/ 166 /* line in mute left & right*/
278 wm8731_write(LINVOL, 0x100 | 0x80); 167 wmcodec_write(LINVOL, 0x100 | 0x80);
279 168
280 /* set DACSEL=0, MUTEMIC=1 */ 169 /* set DACSEL=0, MUTEMIC=1 */
281 wm8731_write(0x4, 0x2); 170 wmcodec_write(0x4, 0x2);
282 171
283 /* set POWEROFF=0 OUTPD=0 DACPD=1 */ 172 /* set POWEROFF=0 OUTPD=0 DACPD=1 */
284 wm8731_write(PWRMGMT, 0x6f); 173 wmcodec_write(PWRMGMT, 0x6f);
285 174
286 /* set POWEROFF=1 OUTPD=1 DACPD=1 */ 175 /* set POWEROFF=1 OUTPD=1 DACPD=1 */
287 wm8731_write(PWRMGMT, 0xff); 176 wmcodec_write(PWRMGMT, 0xff);
288} 177}
289 178
290/* Change the order of the noise shaper, 5th order is recommended above 32kHz */ 179/* Change the order of the noise shaper, 5th order is recommended above 32kHz */
@@ -296,7 +185,7 @@ void wmcodec_set_nsorder(int order)
296void wmcodec_set_sample_rate(int sampling_control) 185void wmcodec_set_sample_rate(int sampling_control)
297{ 186{
298 codec_set_active(0x0); 187 codec_set_active(0x0);
299 wm8731_write(SAMPCTRL, sampling_control); 188 wmcodec_write(SAMPCTRL, sampling_control);
300 codec_set_active(0x1); 189 codec_set_active(0x1);
301} 190}
302 191
diff --git a/firmware/drivers/wm8758.c b/firmware/drivers/wm8758.c
index 33960af9b4..bdc9c8b450 100644
--- a/firmware/drivers/wm8758.c
+++ b/firmware/drivers/wm8758.c
@@ -37,9 +37,8 @@
37#include "buffer.h" 37#include "buffer.h"
38#include "audio.h" 38#include "audio.h"
39 39
40#include "i2c-pp5020.h" 40#include "wmcodec.h"
41#include "wm8758.h" 41#include "wm8758.h"
42#include "pcf50605.h"
43 42
44void wmcodec_reset(void); 43void wmcodec_reset(void);
45 44
@@ -48,67 +47,6 @@ void wmcodec_reset(void);
48//#define BASSCTRL 0x 47//#define BASSCTRL 0x
49//#define TREBCTRL 0x0b 48//#define TREBCTRL 0x0b
50 49
51/*
52 * Reset the I2S BIT.FORMAT I2S, 16bit, FIFO.FORMAT 32bit
53 */
54static void i2s_reset(void)
55{
56 /* PP502x */
57
58 /* I2S soft reset */
59 outl(inl(0x70002800) | 0x80000000, 0x70002800);
60 outl(inl(0x70002800) & ~0x80000000, 0x70002800);
61
62 /* BIT.FORMAT [11:10] = I2S (default) */
63 outl(inl(0x70002800) & ~0xc00, 0x70002800);
64 /* BIT.SIZE [9:8] = 16bit (default) */
65 outl(inl(0x70002800) & ~0x300, 0x70002800);
66
67 /* FIFO.FORMAT [6:4] = 32 bit LSB */
68 /* since BIT.SIZ < FIFO.FORMAT low 16 bits will be 0 */
69 outl(inl(0x70002800) | 0x30, 0x70002800);
70
71 /* RX_ATN_LVL=1 == when 12 slots full */
72 /* TX_ATN_LVL=1 == when 12 slots empty */
73 outl(inl(0x7000280c) | 0x33, 0x7000280c);
74
75 /* Rx.CLR = 1, TX.CLR = 1 */
76 outl(inl(0x7000280c) | 0x1100, 0x7000280c);
77}
78
79void wm8758_write(int reg, int data)
80{
81 ipod_i2c_send(0x1a, (reg<<1) | ((data&0x100)>>8),data&0xff);
82}
83
84/*
85 * Initialise the WM8758 for playback via headphone and line out.
86 * Note, I'm using the WM8750 datasheet as its apparently close.
87 */
88int wmcodec_init(void) {
89 /* normal outputs for CDI and I2S pin groups */
90 outl(inl(0x70000020) & ~0x300, 0x70000020);
91
92 /*mini2?*/
93 outl(inl(0x70000010) & ~0x3000000, 0x70000010);
94 /*mini2?*/
95
96 /* device reset */
97 outl(inl(0x60006004) | 0x800, 0x60006004);
98 outl(inl(0x60006004) & ~0x800, 0x60006004);
99
100 /* device enable */
101 outl(inl(0x6000600C) | 0x807, 0x6000600C);
102
103 /* enable external dev clock clocks */
104 outl(inl(0x6000600c) | 0x2, 0x6000600c);
105
106 /* external dev clock to 24MHz */
107 outl(inl(0x70000018) & ~0xc, 0x70000018);
108
109 return 0;
110}
111
112/* Silently enable / disable audio output */ 50/* Silently enable / disable audio output */
113void wmcodec_enable_output(bool enable) 51void wmcodec_enable_output(bool enable)
114{ 52{
@@ -119,23 +57,23 @@ void wmcodec_enable_output(bool enable)
119 57
120 /* TODO: Review the power-up sequence to prevent pops */ 58 /* TODO: Review the power-up sequence to prevent pops */
121 59
122 wm8758_write(RESET, 0x1ff); /*Reset*/ 60 wmcodec_write(RESET, 0x1ff); /*Reset*/
123 61
124 wm8758_write(PWRMGMT1, 0x2b); 62 wmcodec_write(PWRMGMT1, 0x2b);
125 wm8758_write(PWRMGMT2, 0x180); 63 wmcodec_write(PWRMGMT2, 0x180);
126 wm8758_write(PWRMGMT3, 0x6f); 64 wmcodec_write(PWRMGMT3, 0x6f);
127 65
128 wm8758_write(AINTFCE, 0x10); 66 wmcodec_write(AINTFCE, 0x10);
129 wm8758_write(CLKCTRL, 0x49); 67 wmcodec_write(CLKCTRL, 0x49);
130 68
131 wm8758_write(OUTCTRL, 1); 69 wmcodec_write(OUTCTRL, 1);
132 70
133 /* The iPod can handle multiple frequencies, but fix at 44.1KHz 71 /* The iPod can handle multiple frequencies, but fix at 44.1KHz
134 for now */ 72 for now */
135 wmcodec_set_sample_rate(WM8758_44100HZ); 73 wmcodec_set_sample_rate(WM8758_44100HZ);
136 74
137 wm8758_write(LOUTMIX,0x1); /* Enable mixer */ 75 wmcodec_write(LOUTMIX,0x1); /* Enable mixer */
138 wm8758_write(ROUTMIX,0x1); /* Enable mixer */ 76 wmcodec_write(ROUTMIX,0x1); /* Enable mixer */
139 wmcodec_mute(0); 77 wmcodec_mute(0);
140 } else { 78 } else {
141 wmcodec_mute(1); 79 wmcodec_mute(1);
@@ -145,8 +83,8 @@ void wmcodec_enable_output(bool enable)
145int wmcodec_set_master_vol(int vol_l, int vol_r) 83int wmcodec_set_master_vol(int vol_l, int vol_r)
146{ 84{
147 /* OUT1 */ 85 /* OUT1 */
148 wm8758_write(LOUT1VOL, 0x080 | vol_l); 86 wmcodec_write(LOUT1VOL, 0x080 | vol_l);
149 wm8758_write(ROUT1VOL, 0x180 | vol_r); 87 wmcodec_write(ROUT1VOL, 0x180 | vol_r);
150 88
151 return 0; 89 return 0;
152} 90}
@@ -154,8 +92,8 @@ int wmcodec_set_master_vol(int vol_l, int vol_r)
154int wmcodec_set_lineout_vol(int vol_l, int vol_r) 92int wmcodec_set_lineout_vol(int vol_l, int vol_r)
155{ 93{
156 /* OUT2 */ 94 /* OUT2 */
157 wm8758_write(LOUT2VOL, vol_l); 95 wmcodec_write(LOUT2VOL, vol_l);
158 wm8758_write(ROUT2VOL, 0x100 | vol_r); 96 wmcodec_write(ROUT2VOL, 0x100 | vol_r);
159 97
160 return 0; 98 return 0;
161} 99}
@@ -178,7 +116,7 @@ void wmcodec_set_bass(int value)
178 116
179 if ((value >= -6) && (value <= 9)) { 117 if ((value >= -6) && (value <= 9)) {
180 /* We use linear bass control with 130Hz cutoff */ 118 /* We use linear bass control with 130Hz cutoff */
181 wm8758_write(BASSCTRL, regvalues[value+6]); 119 wmcodec_write(BASSCTRL, regvalues[value+6]);
182 } 120 }
183#endif 121#endif
184} 122}
@@ -192,7 +130,7 @@ void wmcodec_set_treble(int value)
192 130
193 if ((value >= -6) && (value <= 9)) { 131 if ((value >= -6) && (value <= 9)) {
194 /* We use a 8Khz cutoff */ 132 /* We use a 8Khz cutoff */
195 wm8758_write(TREBCTRL, regvalues[value+6]); 133 wmcodec_write(TREBCTRL, regvalues[value+6]);
196 } 134 }
197#endif 135#endif
198 136
@@ -203,10 +141,10 @@ int wmcodec_mute(int mute)
203 if (mute) 141 if (mute)
204 { 142 {
205 /* Set DACMU = 1 to soft-mute the audio DACs. */ 143 /* Set DACMU = 1 to soft-mute the audio DACs. */
206 wm8758_write(DACCTRL, 0x40); 144 wmcodec_write(DACCTRL, 0x40);
207 } else { 145 } else {
208 /* Set DACMU = 0 to soft-un-mute the audio DACs. */ 146 /* Set DACMU = 0 to soft-un-mute the audio DACs. */
209 wm8758_write(DACCTRL, 0x0); 147 wmcodec_write(DACCTRL, 0x0);
210 } 148 }
211 149
212 return 0; 150 return 0;
@@ -217,11 +155,11 @@ void wmcodec_close(void)
217{ 155{
218 wmcodec_mute(1); 156 wmcodec_mute(1);
219 157
220 wm8758_write(PWRMGMT3, 0x0); 158 wmcodec_write(PWRMGMT3, 0x0);
221 159
222 wm8758_write(PWRMGMT1, 0x0); 160 wmcodec_write(PWRMGMT1, 0x0);
223 161
224 wm8758_write(PWRMGMT2, 0x40); 162 wmcodec_write(PWRMGMT2, 0x40);
225} 163}
226 164
227/* Change the order of the noise shaper, 5th order is recommended above 32kHz */ 165/* Change the order of the noise shaper, 5th order is recommended above 32kHz */
@@ -237,19 +175,19 @@ void wmcodec_set_sample_rate(int sampling_control)
237 (void)sampling_control; 175 (void)sampling_control;
238 176
239 /* set clock div */ 177 /* set clock div */
240 wm8758_write(CLKCTRL, 1 | (0 << 2) | (2 << 5)); 178 wmcodec_write(CLKCTRL, 1 | (0 << 2) | (2 << 5));
241 179
242 /* setup PLL for MHZ=11.2896 */ 180 /* setup PLL for MHZ=11.2896 */
243 wm8758_write(PLLN, (1 << 4) | 0x7); 181 wmcodec_write(PLLN, (1 << 4) | 0x7);
244 wm8758_write(PLLK1, 0x21); 182 wmcodec_write(PLLK1, 0x21);
245 wm8758_write(PLLK2, 0x161); 183 wmcodec_write(PLLK2, 0x161);
246 wm8758_write(PLLK3, 0x26); 184 wmcodec_write(PLLK3, 0x26);
247 185
248 /* set clock div */ 186 /* set clock div */
249 wm8758_write(CLKCTRL, 1 | (1 << 2) | (2 << 5) | (1 << 8)); 187 wmcodec_write(CLKCTRL, 1 | (1 << 2) | (2 << 5) | (1 << 8));
250 188
251 /* set srate */ 189 /* set srate */
252 wm8758_write(SRATECTRL, (0 << 1)); 190 wmcodec_write(SRATECTRL, (0 << 1));
253} 191}
254 192
255void wmcodec_enable_recording(bool source_mic) 193void wmcodec_enable_recording(bool source_mic)
@@ -286,14 +224,14 @@ void wmcodec_set_equalizer_band(int band, int freq, int bw, int gain)
286 eq |= 12 - gain; 224 eq |= 12 - gain;
287 225
288 if (band == 0) { 226 if (band == 0) {
289 wm8758_write(EQ1, eq | 0x100); /* Always apply EQ to the DAC path */ 227 wmcodec_write(EQ1, eq | 0x100); /* Always apply EQ to the DAC path */
290 } else if (band == 1) { 228 } else if (band == 1) {
291 wm8758_write(EQ2, eq); 229 wmcodec_write(EQ2, eq);
292 } else if (band == 2) { 230 } else if (band == 2) {
293 wm8758_write(EQ3, eq); 231 wmcodec_write(EQ3, eq);
294 } else if (band == 3) { 232 } else if (band == 3) {
295 wm8758_write(EQ4, eq); 233 wmcodec_write(EQ4, eq);
296 } else if (band == 4) { 234 } else if (band == 4) {
297 wm8758_write(EQ5, eq); 235 wmcodec_write(EQ5, eq);
298 } 236 }
299} 237}
diff --git a/firmware/drivers/wm8975.c b/firmware/drivers/wm8975.c
index 64a123b883..a961356222 100644
--- a/firmware/drivers/wm8975.c
+++ b/firmware/drivers/wm8975.c
@@ -37,77 +37,13 @@
37#include "buffer.h" 37#include "buffer.h"
38#include "audio.h" 38#include "audio.h"
39 39
40#include "i2c-pp5020.h" 40#include "wmcodec.h"
41#include "wm8975.h" 41#include "wm8975.h"
42#include "pcf50605.h"
43 42
44void wmcodec_reset(void); 43void wmcodec_reset(void);
45 44
46#define IPOD_PCM_LEVEL 0x65 /* -6dB */ 45#define IPOD_PCM_LEVEL 0x65 /* -6dB */
47 46
48/*
49 * Reset the I2S BIT.FORMAT I2S, 16bit, FIFO.FORMAT 32bit
50 */
51static void i2s_reset(void)
52{
53 /* PP502x */
54
55 /* I2S soft reset */
56 outl(inl(0x70002800) | 0x80000000, 0x70002800);
57 outl(inl(0x70002800) & ~0x80000000, 0x70002800);
58
59 /* BIT.FORMAT [11:10] = I2S (default) */
60 outl(inl(0x70002800) & ~0xc00, 0x70002800);
61 /* BIT.SIZE [9:8] = 16bit (default) */
62 outl(inl(0x70002800) & ~0x300, 0x70002800);
63
64 /* FIFO.FORMAT [6:4] = 32 bit LSB */
65 /* since BIT.SIZ < FIFO.FORMAT low 16 bits will be 0 */
66 outl(inl(0x70002800) | 0x30, 0x70002800);
67
68 /* RX_ATN_LVL=1 == when 12 slots full */
69 /* TX_ATN_LVL=1 == when 12 slots empty */
70 outl(inl(0x7000280c) | 0x33, 0x7000280c);
71
72 /* Rx.CLR = 1, TX.CLR = 1 */
73 outl(inl(0x7000280c) | 0x1100, 0x7000280c);
74}
75
76void wm8975_write(int reg, int data)
77{
78 ipod_i2c_send(0x1a, (reg<<1) | ((data&0x100)>>8),data&0xff);
79}
80
81/*
82 * Initialise the WM8975 for playback via headphone and line out.
83 * Note, I'm using the WM8750 datasheet as its apparently close.
84 */
85int wmcodec_init(void) {
86 /* reset I2C */
87 i2c_init();
88
89 /* normal outputs for CDI and I2S pin groups */
90 outl(inl(0x70000020) & ~0x300, 0x70000020);
91
92 /*mini2?*/
93 outl(inl(0x70000010) & ~0x3000000, 0x70000010);
94 /*mini2?*/
95
96 /* device reset */
97 outl(inl(0x60006004) | 0x800, 0x60006004);
98 outl(inl(0x60006004) & ~0x800, 0x60006004);
99
100 /* device enable */
101 outl(inl(0x6000600C) | 0x807, 0x6000600C);
102
103 /* enable external dev clock clocks */
104 outl(inl(0x6000600c) | 0x2, 0x6000600c);
105
106 /* external dev clock to 24MHz */
107 outl(inl(0x70000018) & ~0xc, 0x70000018);
108
109 return 0;
110}
111 47
112/* Silently enable / disable audio output */ 48/* Silently enable / disable audio output */
113void wmcodec_enable_output(bool enable) 49void wmcodec_enable_output(bool enable)
@@ -124,39 +60,39 @@ void wmcodec_enable_output(bool enable)
124 * and Headphone outputs are all OFF (DACMU = 1 Power 60 * and Headphone outputs are all OFF (DACMU = 1 Power
125 * Management registers 1 and 2 are all zeros). 61 * Management registers 1 and 2 are all zeros).
126 */ 62 */
127 wm8975_write(RESET, 0x1ff); /*Reset*/ 63 wmcodec_write(RESET, 0x1ff); /*Reset*/
128 wm8975_write(RESET, 0x0); 64 wmcodec_write(RESET, 0x0);
129 65
130 /* 2. Enable Vmid and VREF. */ 66 /* 2. Enable Vmid and VREF. */
131 wm8975_write(PWRMGMT1, 0xc0); /*Pwr Mgmt(1)*/ 67 wmcodec_write(PWRMGMT1, 0xc0); /*Pwr Mgmt(1)*/
132 68
133 /* 3. Enable DACs as required. */ 69 /* 3. Enable DACs as required. */
134 wm8975_write(PWRMGMT2, 0x180); /*Pwr Mgmt(2)*/ 70 wmcodec_write(PWRMGMT2, 0x180); /*Pwr Mgmt(2)*/
135 71
136 /* 4. Enable line and / or headphone output buffers as required. */ 72 /* 4. Enable line and / or headphone output buffers as required. */
137 wm8975_write(PWRMGMT2, 0x1f8); /*Pwr Mgmt(2)*/ 73 wmcodec_write(PWRMGMT2, 0x1f8); /*Pwr Mgmt(2)*/
138 74
139 /* BCLKINV=0(Dont invert BCLK) MS=1(Enable Master) LRSWAP=0 LRP=0 */ 75 /* BCLKINV=0(Dont invert BCLK) MS=1(Enable Master) LRSWAP=0 LRP=0 */
140 /* IWL=00(16 bit) FORMAT=10(I2S format) */ 76 /* IWL=00(16 bit) FORMAT=10(I2S format) */
141 wm8975_write(AINTFCE, 0x42); 77 wmcodec_write(AINTFCE, 0x42);
142 78
143 /* The iPod can handle multiple frequencies, but fix at 44.1KHz for now */ 79 /* The iPod can handle multiple frequencies, but fix at 44.1KHz for now */
144 wmcodec_set_sample_rate(WM8975_44100HZ); 80 wmcodec_set_sample_rate(WM8975_44100HZ);
145 81
146 /* set the volume to -6dB */ 82 /* set the volume to -6dB */
147 wm8975_write(LOUT1VOL, IPOD_PCM_LEVEL); 83 wmcodec_write(LOUT1VOL, IPOD_PCM_LEVEL);
148 wm8975_write(ROUT1VOL,0x100 | IPOD_PCM_LEVEL); 84 wmcodec_write(ROUT1VOL,0x100 | IPOD_PCM_LEVEL);
149 wm8975_write(LOUT1VOL, IPOD_PCM_LEVEL); 85 wmcodec_write(LOUT1VOL, IPOD_PCM_LEVEL);
150 wm8975_write(ROUT1VOL,0x100 | IPOD_PCM_LEVEL); 86 wmcodec_write(ROUT1VOL,0x100 | IPOD_PCM_LEVEL);
151 87
152 wm8975_write(LOUTMIX1, 0x150); /* Left out Mix(def) */ 88 wmcodec_write(LOUTMIX1, 0x150); /* Left out Mix(def) */
153 wm8975_write(LOUTMIX2, 0x50); 89 wmcodec_write(LOUTMIX2, 0x50);
154 90
155 wm8975_write(ROUTMIX1, 0x50); /* Right out Mix(def) */ 91 wmcodec_write(ROUTMIX1, 0x50); /* Right out Mix(def) */
156 wm8975_write(ROUTMIX2, 0x150); 92 wmcodec_write(ROUTMIX2, 0x150);
157 93
158 wm8975_write(MOUTMIX1, 0x0); /* Mono out Mix */ 94 wmcodec_write(MOUTMIX1, 0x0); /* Mono out Mix */
159 wm8975_write(MOUTMIX2, 0x0); 95 wmcodec_write(MOUTMIX2, 0x0);
160 96
161 wmcodec_mute(0); 97 wmcodec_mute(0);
162 } else { 98 } else {
@@ -173,8 +109,8 @@ int wmcodec_set_master_vol(int vol_l, int vol_r)
173 /* 0101111 == mute (0x2f) */ 109 /* 0101111 == mute (0x2f) */
174 110
175 /* OUT1 */ 111 /* OUT1 */
176 wm8975_write(LOUT1VOL, vol_l); 112 wmcodec_write(LOUT1VOL, vol_l);
177 wm8975_write(ROUT1VOL, 0x100 | vol_r); 113 wmcodec_write(ROUT1VOL, 0x100 | vol_r);
178 114
179 return 0; 115 return 0;
180} 116}
@@ -182,8 +118,8 @@ int wmcodec_set_master_vol(int vol_l, int vol_r)
182int wmcodec_set_lineout_vol(int vol_l, int vol_r) 118int wmcodec_set_lineout_vol(int vol_l, int vol_r)
183{ 119{
184 /* OUT2 */ 120 /* OUT2 */
185 wm8975_write(LOUT2VOL, vol_l); 121 wmcodec_write(LOUT2VOL, vol_l);
186 wm8975_write(ROUT2VOL, 0x100 | vol_r); 122 wmcodec_write(ROUT2VOL, 0x100 | vol_r);
187 123
188 return 0; 124 return 0;
189} 125}
@@ -203,7 +139,7 @@ void wmcodec_set_bass(int value)
203 139
204 if ((value >= -6) && (value <= 9)) { 140 if ((value >= -6) && (value <= 9)) {
205 /* We use linear bass control with 130Hz cutoff */ 141 /* We use linear bass control with 130Hz cutoff */
206 wm8975_write(BASSCTRL, regvalues[value+6]); 142 wmcodec_write(BASSCTRL, regvalues[value+6]);
207 } 143 }
208} 144}
209 145
@@ -213,7 +149,7 @@ void wmcodec_set_treble(int value)
213 149
214 if ((value >= -6) && (value <= 9)) { 150 if ((value >= -6) && (value <= 9)) {
215 /* We use a 8Khz cutoff */ 151 /* We use a 8Khz cutoff */
216 wm8975_write(TREBCTRL, regvalues[value+6]); 152 wmcodec_write(TREBCTRL, regvalues[value+6]);
217 } 153 }
218} 154}
219 155
@@ -222,10 +158,10 @@ int wmcodec_mute(int mute)
222 if (mute) 158 if (mute)
223 { 159 {
224 /* Set DACMU = 1 to soft-mute the audio DACs. */ 160 /* Set DACMU = 1 to soft-mute the audio DACs. */
225 wm8975_write(DACCTRL, 0x8); 161 wmcodec_write(DACCTRL, 0x8);
226 } else { 162 } else {
227 /* Set DACMU = 0 to soft-un-mute the audio DACs. */ 163 /* Set DACMU = 0 to soft-un-mute the audio DACs. */
228 wm8975_write(DACCTRL, 0x0); 164 wmcodec_write(DACCTRL, 0x0);
229 } 165 }
230 166
231 return 0; 167 return 0;
@@ -235,13 +171,13 @@ int wmcodec_mute(int mute)
235void wmcodec_close(void) 171void wmcodec_close(void)
236{ 172{
237 /* 1. Set DACMU = 1 to soft-mute the audio DACs. */ 173 /* 1. Set DACMU = 1 to soft-mute the audio DACs. */
238 wm8975_write(DACCTRL, 0x8); 174 wmcodec_write(DACCTRL, 0x8);
239 175
240 /* 2. Disable all output buffers. */ 176 /* 2. Disable all output buffers. */
241 wm8975_write(PWRMGMT2, 0x0); /*Pwr Mgmt(2)*/ 177 wmcodec_write(PWRMGMT2, 0x0); /*Pwr Mgmt(2)*/
242 178
243 /* 3. Switch off the power supplies. */ 179 /* 3. Switch off the power supplies. */
244 wm8975_write(PWRMGMT1, 0x0); /*Pwr Mgmt(1)*/ 180 wmcodec_write(PWRMGMT1, 0x0); /*Pwr Mgmt(1)*/
245} 181}
246 182
247/* Change the order of the noise shaper, 5th order is recommended above 32kHz */ 183/* Change the order of the noise shaper, 5th order is recommended above 32kHz */
@@ -253,7 +189,7 @@ void wmcodec_set_nsorder(int order)
253/* Note: Disable output before calling this function */ 189/* Note: Disable output before calling this function */
254void wmcodec_set_sample_rate(int sampling_control) { 190void wmcodec_set_sample_rate(int sampling_control) {
255 191
256 wm8975_write(0x08, sampling_control); 192 wmcodec_write(0x08, sampling_control);
257 193
258} 194}
259 195
diff --git a/firmware/export/wmcodec.h b/firmware/export/wmcodec.h
new file mode 100644
index 0000000000..f1c5e20ea9
--- /dev/null
+++ b/firmware/export/wmcodec.h
@@ -0,0 +1,23 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Marcoen Hirschberg
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20void i2s_reset(void);
21int wmcodec_init(void);
22void wmcodec_write(int reg, int data);
23
diff --git a/firmware/target/arm/gigabeat/meg-fx/wmcodec-meg-fx.c b/firmware/target/arm/gigabeat/meg-fx/wmcodec-meg-fx.c
new file mode 100644
index 0000000000..a793f5a1f4
--- /dev/null
+++ b/firmware/target/arm/gigabeat/meg-fx/wmcodec-meg-fx.c
@@ -0,0 +1,61 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Gigabeat specific code for the Wolfson codec
11 *
12 * Based on code from the ipodlinux project - http://ipodlinux.org/
13 * Adapted for Rockbox in December 2005
14 *
15 * Original file: linux/arch/armnommu/mach-ipod/audio.c
16 *
17 * Copyright (c) 2003-2005 Bernard Leach (leachbj@bouncycastle.org)
18 *
19 * All files in this archive are subject to the GNU General Public License.
20 * See the file COPYING in the source tree root for full license agreement.
21 *
22 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
23 * KIND, either express or implied.
24 *
25 ****************************************************************************/
26#include "lcd.h"
27#include "cpu.h"
28#include "kernel.h"
29#include "thread.h"
30#include "power.h"
31#include "debug.h"
32#include "system.h"
33#include "sprintf.h"
34#include "button.h"
35#include "string.h"
36#include "file.h"
37#include "buffer.h"
38#include "audio.h"
39#include "i2c.h"
40/*
41 * Reset the I2S BIT.FORMAT I2S, 16bit, FIFO.FORMAT 32bit
42 */
43void i2s_reset(void)
44{
45}
46
47/*
48 * Initialise the WM8975 for playback via headphone and line out.
49 * Note, I'm using the WM8750 datasheet as its apparently close.
50 */
51int wmcodec_init(void) {
52 /* reset I2C */
53 i2c_init();
54
55 return 0;
56}
57
58void wmcodec_write(int reg, int data)
59{
60 i2c_send(0x34, (reg<<1) | ((data&0x100)>>8),data&0xff);
61}
diff --git a/firmware/target/arm/wmcodec-pp.c b/firmware/target/arm/wmcodec-pp.c
new file mode 100644
index 0000000000..e9626220e7
--- /dev/null
+++ b/firmware/target/arm/wmcodec-pp.c
@@ -0,0 +1,156 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Portalplayer specific code for Wolfson audio codecs
11 *
12 * Based on code from the ipodlinux project - http://ipodlinux.org/
13 * Adapted for Rockbox in December 2005
14 *
15 * Original file: linux/arch/armnommu/mach-ipod/audio.c
16 *
17 * Copyright (c) 2003-2005 Bernard Leach (leachbj@bouncycastle.org)
18 *
19 * All files in this archive are subject to the GNU General Public License.
20 * See the file COPYING in the source tree root for full license agreement.
21 *
22 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
23 * KIND, either express or implied.
24 *
25 ****************************************************************************/
26#include "lcd.h"
27#include "cpu.h"
28#include "kernel.h"
29#include "thread.h"
30#include "power.h"
31#include "debug.h"
32#include "system.h"
33#include "sprintf.h"
34#include "button.h"
35#include "string.h"
36#include "file.h"
37#include "buffer.h"
38#include "audio.h"
39
40#if CONFIG_CPU == PP5020
41#include "i2c-pp5020.h"
42#elif CONFIG_CPU == PP5002
43#include "i2c-pp5002.h"
44#endif
45
46/*
47 * Reset the I2S BIT.FORMAT I2S, 16bit, FIFO.FORMAT 32bit
48 */
49void i2s_reset(void)
50{
51#if CONFIG_CPU == PP5020
52 /* I2S soft reset */
53 outl(inl(0x70002800) | 0x80000000, 0x70002800);
54 outl(inl(0x70002800) & ~0x80000000, 0x70002800);
55
56 /* BIT.FORMAT [11:10] = I2S (default) */
57 outl(inl(0x70002800) & ~0xc00, 0x70002800);
58 /* BIT.SIZE [9:8] = 16bit (default) */
59 outl(inl(0x70002800) & ~0x300, 0x70002800);
60
61 /* FIFO.FORMAT [6:4] = 32 bit LSB */
62 /* since BIT.SIZ < FIFO.FORMAT low 16 bits will be 0 */
63 outl(inl(0x70002800) | 0x30, 0x70002800);
64
65 /* RX_ATN_LVL=1 == when 12 slots full */
66 /* TX_ATN_LVL=1 == when 12 slots empty */
67 outl(inl(0x7000280c) | 0x33, 0x7000280c);
68
69 /* Rx.CLR = 1, TX.CLR = 1 */
70 outl(inl(0x7000280c) | 0x1100, 0x7000280c);
71#elif CONFIG_CPU == PP5002
72 /* I2S device reset */
73 outl(inl(0xcf005030) | 0x80, 0xcf005030);
74 outl(inl(0xcf005030) & ~0x80, 0xcf005030);
75
76 /* I2S controller enable */
77 outl(inl(0xc0002500) | 0x1, 0xc0002500);
78
79 /* BIT.FORMAT [11:10] = I2S (default) */
80 /* BIT.SIZE [9:8] = 24bit */
81 /* FIFO.FORMAT = 24 bit LSB */
82
83 /* reset DAC and ADC fifo */
84 outl(inl(0xc000251c) | 0x30000, 0xc000251c);
85#endif
86}
87
88/*
89 * Initialise the WM8975 for playback via headphone and line out.
90 * Note, I'm using the WM8750 datasheet as its apparently close.
91 */
92int wmcodec_init(void) {
93 /* reset I2C */
94 i2c_init();
95
96#if CONFIG_CPU == PP5020
97 /* normal outputs for CDI and I2S pin groups */
98 outl(inl(0x70000020) & ~0x300, 0x70000020);
99
100 /*mini2?*/
101 outl(inl(0x70000010) & ~0x3000000, 0x70000010);
102 /*mini2?*/
103
104 /* device reset */
105 outl(inl(0x60006004) | 0x800, 0x60006004);
106 outl(inl(0x60006004) & ~0x800, 0x60006004);
107
108 /* device enable */
109 outl(inl(0x6000600C) | 0x807, 0x6000600C);
110
111 /* enable external dev clock clocks */
112 outl(inl(0x6000600c) | 0x2, 0x6000600c);
113
114 /* external dev clock to 24MHz */
115 outl(inl(0x70000018) & ~0xc, 0x70000018);
116#else
117 /* device reset */
118 outl(inl(0xcf005030) | 0x80, 0xcf005030);
119 outl(inl(0xcf005030) & ~0x80, 0xcf005030);
120
121 /* device enable */
122 outl(inl(0xcf005000) | 0x80, 0xcf005000);
123
124 /* GPIO D06 enable for output */
125 outl(inl(0xcf00000c) | 0x40, 0xcf00000c);
126 outl(inl(0xcf00001c) & ~0x40, 0xcf00001c);
127 /* bits 11,10 == 01 */
128 outl(inl(0xcf004040) | 0x400, 0xcf004040);
129 outl(inl(0xcf004040) & ~0x800, 0xcf004040);
130
131 outl(inl(0xcf004048) & ~0x1, 0xcf004048);
132
133 outl(inl(0xcf000004) & ~0xf, 0xcf000004);
134 outl(inl(0xcf004044) & ~0xf, 0xcf004044);
135
136 /* C03 = 0 */
137 outl(inl(0xcf000008) | 0x8, 0xcf000008);
138 outl(inl(0xcf000018) | 0x8, 0xcf000018);
139 outl(inl(0xcf000028) & ~0x8, 0xcf000028);
140#endif
141
142 return 0;
143}
144
145void wmcodec_write(int reg, int data)
146{
147/* Todo: Since the ipod_i2c_* functions also work on H10 and possibly other PP
148 targets, these functions should probably be renamed */
149#if defined(IRIVER_H10) || defined(IRIVER_H10_5GB)
150 /* The H10's audio codec uses an I2C address of 0x1b */
151 ipod_i2c_send(0x1b, (reg<<1) | ((data&0x100)>>8),data&0xff);
152#else
153 /* The iPod's audio codecs use an I2C address of 0x1a */
154 ipod_i2c_send(0x1a, (reg<<1) | ((data&0x100)>>8),data&0xff);
155#endif
156}