diff options
Diffstat (limited to 'firmware/drivers/audio/wm8731.c')
-rw-r--r-- | firmware/drivers/audio/wm8731.c | 194 |
1 files changed, 103 insertions, 91 deletions
diff --git a/firmware/drivers/audio/wm8731.c b/firmware/drivers/audio/wm8731.c index 2f882e8fe1..3cfd3e4b92 100644 --- a/firmware/drivers/audio/wm8731.c +++ b/firmware/drivers/audio/wm8731.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * \/ \/ \/ \/ \/ | 7 | * \/ \/ \/ \/ \/ |
8 | * $Id$ | 8 | * $Id$ |
9 | * | 9 | * |
10 | * Driver for WM8731L audio codec | 10 | * Driver for WM8711/WM8721/WM8731 audio codecs |
11 | * | 11 | * |
12 | * Based on code from the ipodlinux project - http://ipodlinux.org/ | 12 | * Based on code from the ipodlinux project - http://ipodlinux.org/ |
13 | * Adapted for Rockbox in January 2006 | 13 | * Adapted for Rockbox in January 2006 |
@@ -43,7 +43,7 @@ const struct sound_settings_info audiohw_settings[] = { | |||
43 | [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0}, | 43 | [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0}, |
44 | [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0}, | 44 | [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0}, |
45 | [SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100}, | 45 | [SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100}, |
46 | #ifdef HAVE_RECORDING | 46 | #if defined(HAVE_WM8731) && defined(HAVE_RECORDING) |
47 | [SOUND_LEFT_GAIN] = {"dB", 1, 1, 0, 31, 23}, | 47 | [SOUND_LEFT_GAIN] = {"dB", 1, 1, 0, 31, 23}, |
48 | [SOUND_RIGHT_GAIN] = {"dB", 1, 1, 0, 31, 23}, | 48 | [SOUND_RIGHT_GAIN] = {"dB", 1, 1, 0, 31, 23}, |
49 | [SOUND_MIC_GAIN] = {"dB", 1, 1, 0, 1, 0}, | 49 | [SOUND_MIC_GAIN] = {"dB", 1, 1, 0, 1, 0}, |
@@ -53,42 +53,57 @@ const struct sound_settings_info audiohw_settings[] = { | |||
53 | /* Init values/shadows | 53 | /* Init values/shadows |
54 | * Ignore bit 8 since that only specifies "both" for updating | 54 | * Ignore bit 8 since that only specifies "both" for updating |
55 | * gains - "RESET" (15h) not included */ | 55 | * gains - "RESET" (15h) not included */ |
56 | static unsigned char wm8731_regs[WM8731_NUM_REGS] = | 56 | static unsigned char wmc_regs[WMC_NUM_REGS] = |
57 | { | 57 | { |
58 | [LINVOL] = 0x97, | 58 | #ifdef HAVE_WM8731 |
59 | [RINVOL] = 0x97, | 59 | [LINVOL] = LINVOL_DEFAULT, |
60 | [LOUTVOL] = 0x79 | ROUTVOL_RZCEN, | 60 | [RINVOL] = RINVOL_DEFAULT, |
61 | [ROUTVOL] = 0x79 | ROUTVOL_RZCEN, | 61 | #endif |
62 | [AAPCTRL] = 0x0a, | 62 | [LOUTVOL] = LOUTVOL_DEFAULT | WMC_OUT_ZCEN, |
63 | [DAPCTRL] = 0x08, | 63 | [ROUTVOL] = LOUTVOL_DEFAULT | WMC_OUT_ZCEN, |
64 | [PDCTRL] = 0x9f, | 64 | #if defined(HAVE_WM8711) || defined(HAVE_WM8731) |
65 | [AINTFCE] = 0x0a, | 65 | /* BYPASS on by default - OFF until needed */ |
66 | [SAMPCTRL] = 0x00, | 66 | [AAPCTRL] = AAPCTRL_DEFAULT & ~AAPCTRL_BYPASS, |
67 | [ACTIVECTRL] = 0x00, | 67 | /* CLKOUT and OSC on by default - OFF unless needed by a target */ |
68 | [PDCTRL] = PDCTRL_DEFAULT | PDCTRL_CLKOUTPD | PDCTRL_OSCPD, | ||
69 | #elif defined(HAVE_WM8721) | ||
70 | /* No BYPASS */ | ||
71 | [AAPCTRL] = AAPCTRL_DEFAULT, | ||
72 | /* No CLKOUT or OSC */ | ||
73 | [PDCTRL] = PDCTRL_DEFAULT, | ||
74 | #endif | ||
75 | [DAPCTRL] = DAPCTRL_DEFAULT, | ||
76 | #ifndef CODEC_SLAVE | ||
77 | [AINTFCE] = AINTFCE_FORMAT_I2S | AINTFCE_IWL_16BIT | AINTFCE_MS, | ||
78 | #else | ||
79 | [AINTFCE] = AINTFCE_FORMAT_I2S | AINTFCE_IWL_16BIT, | ||
80 | #endif | ||
81 | [SAMPCTRL] = SAMPCTRL_DEFAULT, | ||
82 | [ACTIVECTRL] = ACTIVECTRL_DEFAULT, | ||
68 | }; | 83 | }; |
69 | 84 | ||
70 | static void wm8731_write(int reg, unsigned val) | 85 | static void wmc_write(int reg, unsigned val) |
71 | { | 86 | { |
72 | if ((unsigned)reg >= WM8731_NUM_REGS) | 87 | if ((unsigned)reg >= WMC_NUM_REGS) |
73 | return; | 88 | return; |
74 | 89 | ||
75 | wm8731_regs[reg] = (unsigned char)val; | 90 | wmc_regs[reg] = (unsigned char)val; |
76 | wmcodec_write(reg, val); | 91 | wmcodec_write(reg, val); |
77 | } | 92 | } |
78 | 93 | ||
79 | static void wm8731_set(int reg, unsigned bits) | 94 | static void wmc_set(int reg, unsigned bits) |
80 | { | 95 | { |
81 | wm8731_write(reg, wm8731_regs[reg] | bits); | 96 | wmc_write(reg, wmc_regs[reg] | bits); |
82 | } | 97 | } |
83 | 98 | ||
84 | static void wm8731_clear(int reg, unsigned bits) | 99 | static void wmc_clear(int reg, unsigned bits) |
85 | { | 100 | { |
86 | wm8731_write(reg, wm8731_regs[reg] & ~bits); | 101 | wmc_write(reg, wmc_regs[reg] & ~bits); |
87 | } | 102 | } |
88 | 103 | ||
89 | static void wm8731_write_masked(int reg, unsigned bits, unsigned mask) | 104 | static void wmc_write_masked(int reg, unsigned bits, unsigned mask) |
90 | { | 105 | { |
91 | wm8731_write(reg, (wm8731_regs[reg] & ~mask) | (bits & mask)); | 106 | wmc_write(reg, (wmc_regs[reg] & ~mask) | (bits & mask)); |
92 | } | 107 | } |
93 | 108 | ||
94 | /* convert tenth of dB volume (-730..60) to master volume register value */ | 109 | /* convert tenth of dB volume (-730..60) to master volume register value */ |
@@ -134,54 +149,50 @@ void audiohw_mute(bool mute) | |||
134 | { | 149 | { |
135 | if (mute) { | 150 | if (mute) { |
136 | /* Set DACMU = 1 to soft-mute the audio DACs. */ | 151 | /* Set DACMU = 1 to soft-mute the audio DACs. */ |
137 | wm8731_set(DAPCTRL, DAPCTRL_DACMU); | 152 | wmc_set(DAPCTRL, DAPCTRL_DACMU); |
138 | } else { | 153 | } else { |
139 | /* Set DACMU = 0 to soft-un-mute the audio DACs. */ | 154 | /* Set DACMU = 0 to soft-un-mute the audio DACs. */ |
140 | wm8731_clear(DAPCTRL, DAPCTRL_DACMU); | 155 | wmc_clear(DAPCTRL, DAPCTRL_DACMU); |
141 | } | 156 | } |
142 | } | 157 | } |
143 | 158 | ||
144 | static void codec_set_active(int active) | 159 | static void codec_set_active(int active) |
145 | { | 160 | { |
146 | /* set active to 0x0 or 0x1 */ | 161 | /* set active to 0x0 or 0x1 */ |
147 | wm8731_write(ACTIVECTRL, active ? ACTIVECTRL_ACTIVE : 0); | 162 | wmc_write(ACTIVECTRL, active ? ACTIVECTRL_ACTIVE : 0); |
148 | } | 163 | } |
149 | 164 | ||
150 | void audiohw_preinit(void) | 165 | void audiohw_preinit(void) |
151 | { | 166 | { |
152 | /* POWER UP SEQUENCE */ | 167 | /* POWER UP SEQUENCE */ |
153 | /* 1) Switch on power supplies. By default the WM8731 is in Standby Mode, | 168 | /* 1) Switch on power supplies. By default the WM codec is in Standby Mode, |
154 | * the DAC is digitally muted and the Audio Interface and Outputs are | 169 | * the DAC is digitally muted and the Audio Interface and Outputs are |
155 | * all OFF. */ | 170 | * all OFF. */ |
156 | wmcodec_write(RESET, RESET_RESET); | 171 | wmcodec_write(RESET, RESET_RESET); |
157 | 172 | ||
158 | /* 2) Set all required bits in the Power Down register (0Ch) to '0'; | 173 | /* 2) Set all required bits in the Power Down register (0Ch) to '0'; |
159 | * EXCEPT the OUTPD bit, this should be set to '1' (Default). */ | 174 | * EXCEPT the OUTPD bit, this should be set to '1' (Default). */ |
160 | wm8731_clear(PDCTRL, PDCTRL_DACPD | PDCTRL_POWEROFF); | 175 | wmc_clear(PDCTRL, PDCTRL_DACPD | PDCTRL_POWEROFF); |
161 | 176 | ||
162 | /* 3) Set required values in all other registers except 12h (Active). */ | 177 | /* 3) Set required values in all other registers except 12h (Active). */ |
163 | wm8731_write(AINTFCE, | 178 | wmc_set(AINTFCE, 0); /* Set no bits - write init/shadow value */ |
164 | #ifndef CODEC_SLAVE | ||
165 | AINTFCE_MS | | ||
166 | #endif | ||
167 | AINTFCE_FORMAT_I2S | AINTFCE_IWL_16BIT); | ||
168 | 179 | ||
169 | wm8731_set(AAPCTRL, AAPCTRL_DACSEL); | 180 | wmc_set(AAPCTRL, AAPCTRL_DACSEL); |
170 | wm8731_write(SAMPCTRL, WM8731_USB24_44100HZ); | 181 | wmc_write(SAMPCTRL, WMC_USB24_44100HZ); |
182 | |||
183 | /* 4) Set the 'Active' bit in register 12h. */ | ||
184 | codec_set_active(true); | ||
171 | 185 | ||
172 | /* 5) The last write of the sequence should be setting OUTPD to '0' | 186 | /* 5) The last write of the sequence should be setting OUTPD to '0' |
173 | * (active) in register 0Ch, enabling the DAC signal path, free | 187 | * (active) in register 0Ch, enabling the DAC signal path, free |
174 | * of any significant power-up noise. */ | 188 | * of any significant power-up noise. */ |
175 | wm8731_clear(PDCTRL, PDCTRL_OUTPD); | 189 | wmc_clear(PDCTRL, PDCTRL_OUTPD); |
176 | } | 190 | } |
177 | 191 | ||
178 | void audiohw_postinit(void) | 192 | void audiohw_postinit(void) |
179 | { | 193 | { |
180 | sleep(HZ); | 194 | sleep(HZ); |
181 | 195 | ||
182 | /* 4) Set the 'Active' bit in register 12h. */ | ||
183 | codec_set_active(true); | ||
184 | |||
185 | audiohw_mute(false); | 196 | audiohw_mute(false); |
186 | 197 | ||
187 | #if defined(IRIVER_H10) || defined(IRIVER_H10_5GB) | 198 | #if defined(IRIVER_H10) || defined(IRIVER_H10_5GB) |
@@ -197,51 +208,53 @@ void audiohw_set_master_vol(int vol_l, int vol_r) | |||
197 | /* 1111001 == 0dB */ | 208 | /* 1111001 == 0dB */ |
198 | /* 0110000 == -73dB */ | 209 | /* 0110000 == -73dB */ |
199 | /* 0101111 == mute (0x2f) */ | 210 | /* 0101111 == mute (0x2f) */ |
200 | wm8731_write_masked(LOUTVOL, vol_l, LOUTVOL_LHPVOL_MASK); | 211 | wmc_write_masked(LOUTVOL, vol_l, WMC_OUT_VOL_MASK); |
201 | wm8731_write_masked(ROUTVOL, vol_r, ROUTVOL_RHPVOL_MASK); | 212 | wmc_write_masked(ROUTVOL, vol_r, WMC_OUT_VOL_MASK); |
202 | } | 213 | } |
203 | 214 | ||
204 | /* Nice shutdown of WM8731 codec */ | 215 | /* Nice shutdown of WM codec */ |
205 | void audiohw_close(void) | 216 | void audiohw_close(void) |
206 | { | 217 | { |
207 | /* POWER DOWN SEQUENCE */ | 218 | /* POWER DOWN SEQUENCE */ |
208 | /* 1) Set the OUTPD bit to '1' (power down). */ | 219 | /* 1) Set the OUTPD bit to '1' (power down). */ |
209 | wm8731_set(PDCTRL, PDCTRL_OUTPD); | 220 | wmc_set(PDCTRL, PDCTRL_OUTPD); |
210 | /* 2) Remove the WM8731 supplies. */ | 221 | /* 2) Remove the WM codec supplies. */ |
211 | } | 222 | } |
212 | 223 | ||
213 | void audiohw_set_sample_rate(int sampling_control) | 224 | void audiohw_set_sample_rate(int sampling_control) |
214 | { | 225 | { |
215 | int rate = 0; | 226 | int rate; |
216 | 227 | ||
217 | switch(sampling_control) | 228 | switch(sampling_control) |
218 | { | 229 | { |
219 | case SAMPR_96: | 230 | case SAMPR_96: |
220 | rate = WM8731_USB24_96000HZ; | 231 | rate = WMC_USB24_96000HZ; |
221 | break; | 232 | break; |
222 | case SAMPR_88: | 233 | case SAMPR_88: |
223 | rate = WM8731_USB24_88200HZ; | 234 | rate = WMC_USB24_88200HZ; |
224 | break; | 235 | break; |
225 | case SAMPR_48: | 236 | case SAMPR_48: |
226 | rate = WM8731_USB24_48000HZ; | 237 | rate = WMC_USB24_48000HZ; |
227 | break; | 238 | break; |
239 | default: | ||
228 | case SAMPR_44: | 240 | case SAMPR_44: |
229 | rate = WM8731_USB24_44100HZ; | 241 | rate = WMC_USB24_44100HZ; |
230 | break; | 242 | break; |
231 | case SAMPR_32: | 243 | case SAMPR_32: |
232 | rate = WM8731_USB24_32000HZ; | 244 | rate = WMC_USB24_32000HZ; |
233 | break; | 245 | break; |
234 | case SAMPR_8: | 246 | case SAMPR_8: |
235 | rate = WM8731_USB24_8000HZ; | 247 | rate = WMC_USB24_8000HZ; |
236 | break; | 248 | break; |
237 | } | 249 | } |
238 | 250 | ||
239 | codec_set_active(false); | 251 | codec_set_active(false); |
240 | wm8731_write(SAMPCTRL, rate); | 252 | wmc_write(SAMPCTRL, rate); |
241 | codec_set_active(true); | 253 | codec_set_active(true); |
242 | } | 254 | } |
243 | 255 | ||
244 | #ifdef HAVE_RECORDING | 256 | #if defined(HAVE_WM8731) && defined(HAVE_RECORDING) |
257 | /* WM8731 only */ | ||
245 | void audiohw_enable_recording(bool source_mic) | 258 | void audiohw_enable_recording(bool source_mic) |
246 | { | 259 | { |
247 | /* NOTE: When switching to digital monitoring we will not want | 260 | /* NOTE: When switching to digital monitoring we will not want |
@@ -250,27 +263,27 @@ void audiohw_enable_recording(bool source_mic) | |||
250 | codec_set_active(false); | 263 | codec_set_active(false); |
251 | 264 | ||
252 | if (source_mic) { | 265 | if (source_mic) { |
253 | wm8731_set(LINVOL, LINVOL_LINMUTE); | 266 | wmc_set(LINVOL, WMC_IN_MUTE); |
254 | wm8731_set(RINVOL, RINVOL_RINMUTE); | 267 | wmc_set(RINVOL, WMC_IN_MUTE); |
255 | 268 | ||
256 | wm8731_write_masked(PDCTRL, PDCTRL_LINEINPD | PDCTRL_DACPD, | 269 | wmc_write_masked(PDCTRL, PDCTRL_LINEINPD | PDCTRL_DACPD, |
257 | PDCTRL_LINEINPD | PDCTRL_MICPD | | 270 | PDCTRL_LINEINPD | PDCTRL_MICPD | |
258 | PDCTRL_ADCPD | PDCTRL_DACPD); | 271 | PDCTRL_ADCPD | PDCTRL_DACPD); |
259 | wm8731_write_masked(AAPCTRL, AAPCTRL_INSEL | AAPCTRL_SIDETONE, | 272 | wmc_write_masked(AAPCTRL, AAPCTRL_INSEL | AAPCTRL_SIDETONE, |
260 | AAPCTRL_MUTEMIC | AAPCTRL_INSEL | | 273 | AAPCTRL_MUTEMIC | AAPCTRL_INSEL | |
261 | AAPCTRL_BYPASS | AAPCTRL_DACSEL | | 274 | AAPCTRL_BYPASS | AAPCTRL_DACSEL | |
262 | AAPCTRL_SIDETONE); | 275 | AAPCTRL_SIDETONE); |
263 | } else { | 276 | } else { |
264 | wm8731_write_masked(PDCTRL, PDCTRL_MICPD | PDCTRL_DACPD, | 277 | wmc_write_masked(PDCTRL, PDCTRL_MICPD | PDCTRL_DACPD, |
265 | PDCTRL_LINEINPD | PDCTRL_MICPD | | 278 | PDCTRL_LINEINPD | PDCTRL_MICPD | |
266 | PDCTRL_ADCPD | PDCTRL_DACPD); | 279 | PDCTRL_ADCPD | PDCTRL_DACPD); |
267 | wm8731_write_masked(AAPCTRL, AAPCTRL_MUTEMIC | AAPCTRL_BYPASS, | 280 | wmc_write_masked(AAPCTRL, AAPCTRL_MUTEMIC | AAPCTRL_BYPASS, |
268 | AAPCTRL_MUTEMIC | AAPCTRL_INSEL | | 281 | AAPCTRL_MUTEMIC | AAPCTRL_INSEL | |
269 | AAPCTRL_BYPASS | AAPCTRL_DACSEL | | 282 | AAPCTRL_BYPASS | AAPCTRL_DACSEL | |
270 | AAPCTRL_SIDETONE); | 283 | AAPCTRL_SIDETONE); |
271 | 284 | ||
272 | wm8731_clear(LINVOL, LINVOL_LINMUTE); | 285 | wmc_clear(LINVOL, WMC_IN_MUTE); |
273 | wm8731_clear(RINVOL, RINVOL_RINMUTE); | 286 | wmc_clear(RINVOL, WMC_IN_MUTE); |
274 | } | 287 | } |
275 | 288 | ||
276 | codec_set_active(true); | 289 | codec_set_active(true); |
@@ -281,21 +294,21 @@ void audiohw_disable_recording(void) | |||
281 | codec_set_active(false); | 294 | codec_set_active(false); |
282 | 295 | ||
283 | /* Mute line inputs */ | 296 | /* Mute line inputs */ |
284 | wm8731_set(LINVOL, LINVOL_LINMUTE); | 297 | wmc_set(LINVOL, WMC_IN_MUTE); |
285 | wm8731_set(RINVOL, RINVOL_RINMUTE); | 298 | wmc_set(RINVOL, WMC_IN_MUTE); |
286 | wm8731_set(AAPCTRL, AAPCTRL_MUTEMIC); | 299 | wmc_set(AAPCTRL, AAPCTRL_MUTEMIC); |
287 | 300 | ||
288 | /* Turn off input analog audio paths */ | 301 | /* Turn off input analog audio paths */ |
289 | wm8731_clear(AAPCTRL, AAPCTRL_BYPASS | AAPCTRL_SIDETONE); | 302 | wmc_clear(AAPCTRL, AAPCTRL_BYPASS | AAPCTRL_SIDETONE); |
290 | 303 | ||
291 | /* Set power config */ | 304 | /* Set power config */ |
292 | wm8731_write_masked(PDCTRL, | 305 | wmc_write_masked(PDCTRL, |
293 | PDCTRL_LINEINPD | PDCTRL_MICPD | PDCTRL_ADCPD, | 306 | PDCTRL_LINEINPD | PDCTRL_MICPD | PDCTRL_ADCPD, |
294 | PDCTRL_LINEINPD | PDCTRL_MICPD | PDCTRL_DACPD | | 307 | PDCTRL_LINEINPD | PDCTRL_MICPD | PDCTRL_DACPD | |
295 | PDCTRL_ADCPD); | 308 | PDCTRL_ADCPD); |
296 | 309 | ||
297 | /* Select DAC */ | 310 | /* Select DAC */ |
298 | wm8731_set(AAPCTRL, AAPCTRL_DACSEL); | 311 | wmc_set(AAPCTRL, AAPCTRL_DACSEL); |
299 | 312 | ||
300 | codec_set_active(true); | 313 | codec_set_active(true); |
301 | } | 314 | } |
@@ -306,15 +319,15 @@ void audiohw_set_recvol(int left, int right, int type) | |||
306 | { | 319 | { |
307 | case AUDIO_GAIN_MIC: | 320 | case AUDIO_GAIN_MIC: |
308 | if (left > 0) { | 321 | if (left > 0) { |
309 | wm8731_set(AAPCTRL, AAPCTRL_MIC_BOOST); | 322 | wmc_set(AAPCTRL, AAPCTRL_MIC_BOOST); |
310 | } | 323 | } |
311 | else { | 324 | else { |
312 | wm8731_clear(AAPCTRL, AAPCTRL_MIC_BOOST); | 325 | wmc_clear(AAPCTRL, AAPCTRL_MIC_BOOST); |
313 | } | 326 | } |
314 | break; | 327 | break; |
315 | case AUDIO_GAIN_LINEIN: | 328 | case AUDIO_GAIN_LINEIN: |
316 | wm8731_write_masked(LINVOL, left, LINVOL_MASK); | 329 | wmc_write_masked(LINVOL, left, WMC_IN_VOL_MASK); |
317 | wm8731_write_masked(RINVOL, right, RINVOL_MASK); | 330 | wmc_write_masked(RINVOL, right, WMC_IN_VOL_MASK); |
318 | break; | 331 | break; |
319 | default: | 332 | default: |
320 | return; | 333 | return; |
@@ -324,13 +337,12 @@ void audiohw_set_recvol(int left, int right, int type) | |||
324 | void audiohw_set_monitor(bool enable) | 337 | void audiohw_set_monitor(bool enable) |
325 | { | 338 | { |
326 | if(enable) { | 339 | if(enable) { |
327 | wm8731_clear(PDCTRL, PDCTRL_LINEINPD); | 340 | wmc_clear(PDCTRL, PDCTRL_LINEINPD); |
328 | wm8731_set(AAPCTRL, AAPCTRL_BYPASS); | 341 | wmc_set(AAPCTRL, AAPCTRL_BYPASS); |
329 | } | 342 | } |
330 | else { | 343 | else { |
331 | wm8731_clear(AAPCTRL, AAPCTRL_BYPASS); | 344 | wmc_clear(AAPCTRL, AAPCTRL_BYPASS); |
332 | wm8731_set(PDCTRL, PDCTRL_LINEINPD); | 345 | wmc_set(PDCTRL, PDCTRL_LINEINPD); |
333 | } | 346 | } |
334 | } | 347 | } |
335 | #endif /* HAVE_RECORDING */ | 348 | #endif /* HAVE_WM8731 && HAVE_RECORDING */ |
336 | |||