diff options
Diffstat (limited to 'firmware/drivers/audio/wm8758.c')
-rw-r--r-- | firmware/drivers/audio/wm8758.c | 299 |
1 files changed, 299 insertions, 0 deletions
diff --git a/firmware/drivers/audio/wm8758.c b/firmware/drivers/audio/wm8758.c new file mode 100644 index 0000000000..b52bac2f21 --- /dev/null +++ b/firmware/drivers/audio/wm8758.c | |||
@@ -0,0 +1,299 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Driver for WM8758 audio codec - based on datasheet for WM8983 | ||
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 | #include "wmcodec.h" | ||
41 | #include "wm8758.h" | ||
42 | #include "i2s.h" | ||
43 | |||
44 | /* convert tenth of dB volume (-57..6) to master volume register value */ | ||
45 | int tenthdb2master(int db) | ||
46 | { | ||
47 | /* +6 to -57dB in 1dB steps == 64 levels = 6 bits */ | ||
48 | /* 0111111 == +6dB (0x3f) = 63) */ | ||
49 | /* 0111001 == 0dB (0x39) = 57) */ | ||
50 | /* 0000001 == -56dB (0x01) = */ | ||
51 | /* 0000000 == -57dB (0x00) */ | ||
52 | |||
53 | /* 1000000 == Mute (0x40) */ | ||
54 | |||
55 | if (db < VOLUME_MIN) { | ||
56 | return 0x40; | ||
57 | } else { | ||
58 | return((db/10)+57); | ||
59 | } | ||
60 | } | ||
61 | |||
62 | /* convert tenth of dB volume (-780..0) to mixer volume register value */ | ||
63 | int tenthdb2mixer(int db) | ||
64 | { | ||
65 | if (db < -660) /* 1.5 dB steps */ | ||
66 | return (2640 - db) / 15; | ||
67 | else if (db < -600) /* 0.75 dB steps */ | ||
68 | return (990 - db) * 2 / 15; | ||
69 | else if (db < -460) /* 0.5 dB steps */ | ||
70 | return (460 - db) / 5; | ||
71 | else /* 0.25 dB steps */ | ||
72 | return -db * 2 / 5; | ||
73 | } | ||
74 | |||
75 | void audiohw_reset(void); | ||
76 | |||
77 | #define IPOD_PCM_LEVEL 0x65 /* -6dB */ | ||
78 | |||
79 | //#define BASSCTRL 0x | ||
80 | //#define TREBCTRL 0x0b | ||
81 | |||
82 | /* Silently enable / disable audio output */ | ||
83 | void audiohw_enable_output(bool enable) | ||
84 | { | ||
85 | if (enable) | ||
86 | { | ||
87 | /* reset the I2S controller into known state */ | ||
88 | i2s_reset(); | ||
89 | |||
90 | /* TODO: Review the power-up sequence to prevent pops */ | ||
91 | |||
92 | wmcodec_write(RESET, 0x1ff); /*Reset*/ | ||
93 | |||
94 | wmcodec_write(PWRMGMT1, 0x2b); | ||
95 | wmcodec_write(PWRMGMT2, 0x180); | ||
96 | wmcodec_write(PWRMGMT3, 0x6f); | ||
97 | |||
98 | wmcodec_write(AINTFCE, 0x10); | ||
99 | wmcodec_write(CLKCTRL, 0x49); | ||
100 | |||
101 | wmcodec_write(OUTCTRL, 1); | ||
102 | |||
103 | /* The iPod can handle multiple frequencies, but fix at 44.1KHz | ||
104 | for now */ | ||
105 | audiohw_set_sample_rate(WM8758_44100HZ); | ||
106 | |||
107 | wmcodec_write(LOUTMIX,0x1); /* Enable mixer */ | ||
108 | wmcodec_write(ROUTMIX,0x1); /* Enable mixer */ | ||
109 | audiohw_mute(0); | ||
110 | } else { | ||
111 | audiohw_mute(1); | ||
112 | } | ||
113 | } | ||
114 | |||
115 | int audiohw_set_master_vol(int vol_l, int vol_r) | ||
116 | { | ||
117 | /* OUT1 */ | ||
118 | wmcodec_write(LOUT1VOL, 0x080 | vol_l); | ||
119 | wmcodec_write(ROUT1VOL, 0x180 | vol_r); | ||
120 | |||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | int audiohw_set_lineout_vol(int vol_l, int vol_r) | ||
125 | { | ||
126 | /* OUT2 */ | ||
127 | wmcodec_write(LOUT2VOL, vol_l); | ||
128 | wmcodec_write(ROUT2VOL, 0x100 | vol_r); | ||
129 | |||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | int audiohw_set_mixer_vol(int channel1, int channel2) | ||
134 | { | ||
135 | (void)channel1; | ||
136 | (void)channel2; | ||
137 | |||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | /* We are using Linear bass control */ | ||
142 | void audiohw_set_bass(int value) | ||
143 | { | ||
144 | (void)value; | ||
145 | } | ||
146 | |||
147 | void audiohw_set_treble(int value) | ||
148 | { | ||
149 | (void)value; | ||
150 | } | ||
151 | |||
152 | int audiohw_mute(int mute) | ||
153 | { | ||
154 | if (mute) | ||
155 | { | ||
156 | /* Set DACMU = 1 to soft-mute the audio DACs. */ | ||
157 | wmcodec_write(DACCTRL, 0x40); | ||
158 | } else { | ||
159 | /* Set DACMU = 0 to soft-un-mute the audio DACs. */ | ||
160 | wmcodec_write(DACCTRL, 0x0); | ||
161 | } | ||
162 | |||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | /* Nice shutdown of WM8758 codec */ | ||
167 | void audiohw_close(void) | ||
168 | { | ||
169 | audiohw_mute(1); | ||
170 | |||
171 | wmcodec_write(PWRMGMT3, 0x0); | ||
172 | |||
173 | wmcodec_write(PWRMGMT1, 0x0); | ||
174 | |||
175 | wmcodec_write(PWRMGMT2, 0x40); | ||
176 | } | ||
177 | |||
178 | /* Change the order of the noise shaper, 5th order is recommended above 32kHz */ | ||
179 | void audiohw_set_nsorder(int order) | ||
180 | { | ||
181 | (void)order; | ||
182 | } | ||
183 | |||
184 | /* Note: Disable output before calling this function */ | ||
185 | void audiohw_set_sample_rate(int sampling_control) | ||
186 | { | ||
187 | /**** We force 44.1KHz for now. ****/ | ||
188 | (void)sampling_control; | ||
189 | |||
190 | /* set clock div */ | ||
191 | wmcodec_write(CLKCTRL, 1 | (0 << 2) | (2 << 5)); | ||
192 | |||
193 | /* setup PLL for MHZ=11.2896 */ | ||
194 | wmcodec_write(PLLN, (1 << 4) | 0x7); | ||
195 | wmcodec_write(PLLK1, 0x21); | ||
196 | wmcodec_write(PLLK2, 0x161); | ||
197 | wmcodec_write(PLLK3, 0x26); | ||
198 | |||
199 | /* set clock div */ | ||
200 | wmcodec_write(CLKCTRL, 1 | (1 << 2) | (2 << 5) | (1 << 8)); | ||
201 | |||
202 | /* set srate */ | ||
203 | wmcodec_write(SRATECTRL, (0 << 1)); | ||
204 | } | ||
205 | |||
206 | void audiohw_enable_recording(bool source_mic) | ||
207 | { | ||
208 | (void)source_mic; /* We only have a line-in (I think) */ | ||
209 | |||
210 | /* reset the I2S controller into known state */ | ||
211 | i2s_reset(); | ||
212 | |||
213 | wmcodec_write(RESET, 0x1ff); /*Reset*/ | ||
214 | |||
215 | wmcodec_write(PWRMGMT1, 0x2b); | ||
216 | wmcodec_write(PWRMGMT2, 0x18f); /* Enable ADC - 0x0c enables left/right PGA input, and 0x03 turns on power to the ADCs */ | ||
217 | wmcodec_write(PWRMGMT3, 0x6f); | ||
218 | |||
219 | wmcodec_write(AINTFCE, 0x10); | ||
220 | wmcodec_write(CLKCTRL, 0x49); | ||
221 | |||
222 | wmcodec_write(OUTCTRL, 1); | ||
223 | |||
224 | /* The iPod can handle multiple frequencies, but fix at 44.1KHz | ||
225 | for now */ | ||
226 | audiohw_set_sample_rate(WM8758_44100HZ); | ||
227 | |||
228 | wmcodec_write(INCTRL,0x44); /* Connect L2 and R2 inputs */ | ||
229 | |||
230 | /* Set L2/R2_2BOOSTVOL to 0db (bits 4-6) */ | ||
231 | /* 000 = disabled | ||
232 | 001 = -12dB | ||
233 | 010 = -9dB | ||
234 | 011 = -6dB | ||
235 | 100 = -3dB | ||
236 | 101 = 0dB | ||
237 | 110 = 3dB | ||
238 | 111 = 6dB | ||
239 | */ | ||
240 | wmcodec_write(LADCBOOST,0x50); | ||
241 | wmcodec_write(RADCBOOST,0x50); | ||
242 | |||
243 | /* Set L/R input PGA Volume to 0db */ | ||
244 | // wm8758_write(LINPGAVOL,0x3f); | ||
245 | // wm8758_write(RINPGAVOL,0x13f); | ||
246 | |||
247 | /* Enable monitoring */ | ||
248 | wmcodec_write(LOUTMIX,0x17); /* Enable output mixer - BYPL2LMIX @ 0db*/ | ||
249 | wmcodec_write(ROUTMIX,0x17); /* Enable output mixer - BYPR2RMIX @ 0db*/ | ||
250 | |||
251 | audiohw_mute(0); | ||
252 | } | ||
253 | |||
254 | void audiohw_disable_recording(void) { | ||
255 | audiohw_mute(1); | ||
256 | |||
257 | wmcodec_write(PWRMGMT3, 0x0); | ||
258 | |||
259 | wmcodec_write(PWRMGMT1, 0x0); | ||
260 | |||
261 | wmcodec_write(PWRMGMT2, 0x40); | ||
262 | } | ||
263 | |||
264 | void audiohw_set_recvol(int left, int right, int type) { | ||
265 | |||
266 | (void)left; | ||
267 | (void)right; | ||
268 | (void)type; | ||
269 | } | ||
270 | |||
271 | void audiohw_set_monitor(int enable) { | ||
272 | |||
273 | (void)enable; | ||
274 | } | ||
275 | |||
276 | void audiohw_set_equalizer_band(int band, int freq, int bw, int gain) | ||
277 | { | ||
278 | unsigned int eq = 0; | ||
279 | |||
280 | /* Band 1..3 are peak filters */ | ||
281 | if (band >= 1 && band <= 3) { | ||
282 | eq |= (bw << 8); | ||
283 | } | ||
284 | |||
285 | eq |= (freq << 5); | ||
286 | eq |= 12 - gain; | ||
287 | |||
288 | if (band == 0) { | ||
289 | wmcodec_write(EQ1, eq | 0x100); /* Always apply EQ to the DAC path */ | ||
290 | } else if (band == 1) { | ||
291 | wmcodec_write(EQ2, eq); | ||
292 | } else if (band == 2) { | ||
293 | wmcodec_write(EQ3, eq); | ||
294 | } else if (band == 3) { | ||
295 | wmcodec_write(EQ4, eq); | ||
296 | } else if (band == 4) { | ||
297 | wmcodec_write(EQ5, eq); | ||
298 | } | ||
299 | } | ||