diff options
-rw-r--r-- | firmware/drivers/audio/wm8731.c | 162 | ||||
-rw-r--r-- | firmware/export/wm8731.h | 2 |
2 files changed, 86 insertions, 78 deletions
diff --git a/firmware/drivers/audio/wm8731.c b/firmware/drivers/audio/wm8731.c index d96701ca9d..d6e21c34de 100644 --- a/firmware/drivers/audio/wm8731.c +++ b/firmware/drivers/audio/wm8731.c | |||
@@ -53,33 +53,43 @@ const struct sound_settings_info audiohw_settings[] = { | |||
53 | 53 | ||
54 | /* Init values/shadows | 54 | /* Init values/shadows |
55 | * Ignore bit 8 since that only specifies "both" for updating | 55 | * Ignore bit 8 since that only specifies "both" for updating |
56 | * gains */ | 56 | * gains - "RESET" (15h) not included */ |
57 | static unsigned char wm8731_regs[7] = | 57 | static unsigned char wm8731_regs[WM8731_NUM_REGS] = |
58 | { | 58 | { |
59 | [LINVOL] = LINVOL_LINMUTE, | 59 | [LINVOL] = 0x97, |
60 | [RINVOL] = RINVOL_RINMUTE, | 60 | [RINVOL] = 0x97, |
61 | [LOUTVOL] = ROUTVOL_RZCEN, | 61 | [LOUTVOL] = 0x79 | ROUTVOL_RZCEN, |
62 | [ROUTVOL] = ROUTVOL_RZCEN, | 62 | [ROUTVOL] = 0x79 | ROUTVOL_RZCEN, |
63 | [AAPCTRL] = AAPCTRL_MUTEMIC | AAPCTRL_DACSEL, | 63 | [AAPCTRL] = 0x0a, |
64 | [DAPCTRL] = DAPCTRL_DACMU, | 64 | [DAPCTRL] = 0x08, |
65 | [PDCTRL] = PDCTRL_LINEINPD | PDCTRL_MICPD | PDCTRL_ADCPD | | 65 | [PDCTRL] = 0x9f, |
66 | PDCTRL_OUTPD | PDCTRL_OSCPD | PDCTRL_CLKOUTPD, | 66 | [AINTFCE] = 0x0a, |
67 | [SAMPCTRL] = 0x00, | ||
68 | [ACTIVECTRL] = 0x00, | ||
67 | }; | 69 | }; |
68 | 70 | ||
69 | static void wm8731_write(int reg, unsigned val) | 71 | static void wm8731_write(int reg, unsigned val) |
70 | { | 72 | { |
73 | if ((unsigned)reg >= WM8731_NUM_REGS) | ||
74 | return; | ||
75 | |||
71 | wm8731_regs[reg] = (unsigned char)val; | 76 | wm8731_regs[reg] = (unsigned char)val; |
72 | wmcodec_write(reg, val); | 77 | wmcodec_write(reg, val); |
73 | } | 78 | } |
74 | 79 | ||
75 | static void wm8731_write_and(int reg, unsigned bits) | 80 | static void wm8731_set(int reg, unsigned bits) |
76 | { | 81 | { |
77 | wm8731_write(reg, wm8731_regs[reg] & bits); | 82 | wm8731_write(reg, wm8731_regs[reg] | bits); |
78 | } | 83 | } |
79 | 84 | ||
80 | static void wm8731_write_or(int reg, unsigned bits) | 85 | static void wm8731_clear(int reg, unsigned bits) |
81 | { | 86 | { |
82 | wm8731_write(reg, wm8731_regs[reg] | bits); | 87 | wm8731_write(reg, wm8731_regs[reg] & ~bits); |
88 | } | ||
89 | |||
90 | static void wm8731_write_masked(int reg, unsigned bits, unsigned mask) | ||
91 | { | ||
92 | wm8731_write(reg, (wm8731_regs[reg] & ~mask) | (bits & mask)); | ||
83 | } | 93 | } |
84 | 94 | ||
85 | /* convert tenth of dB volume (-730..60) to master volume register value */ | 95 | /* convert tenth of dB volume (-730..60) to master volume register value */ |
@@ -125,17 +135,17 @@ void audiohw_mute(bool mute) | |||
125 | { | 135 | { |
126 | if (mute) { | 136 | if (mute) { |
127 | /* Set DACMU = 1 to soft-mute the audio DACs. */ | 137 | /* Set DACMU = 1 to soft-mute the audio DACs. */ |
128 | wm8731_write_or(DAPCTRL, DAPCTRL_DACMU); | 138 | wm8731_set(DAPCTRL, DAPCTRL_DACMU); |
129 | } else { | 139 | } else { |
130 | /* Set DACMU = 0 to soft-un-mute the audio DACs. */ | 140 | /* Set DACMU = 0 to soft-un-mute the audio DACs. */ |
131 | wm8731_write_and(DAPCTRL, ~DAPCTRL_DACMU); | 141 | wm8731_clear(DAPCTRL, DAPCTRL_DACMU); |
132 | } | 142 | } |
133 | } | 143 | } |
134 | 144 | ||
135 | static void codec_set_active(int active) | 145 | static void codec_set_active(int active) |
136 | { | 146 | { |
137 | /* set active to 0x0 or 0x1 */ | 147 | /* set active to 0x0 or 0x1 */ |
138 | wmcodec_write(ACTIVECTRL, active ? ACTIVECTRL_ACTIVE : 0); | 148 | wm8731_write(ACTIVECTRL, active ? ACTIVECTRL_ACTIVE : 0); |
139 | } | 149 | } |
140 | 150 | ||
141 | void audiohw_preinit(void) | 151 | void audiohw_preinit(void) |
@@ -150,23 +160,22 @@ void audiohw_preinit(void) | |||
150 | 160 | ||
151 | /* 2) Set all required bits in the Power Down register (0Ch) to '0'; | 161 | /* 2) Set all required bits in the Power Down register (0Ch) to '0'; |
152 | * EXCEPT the OUTPD bit, this should be set to '1' (Default). */ | 162 | * EXCEPT the OUTPD bit, this should be set to '1' (Default). */ |
153 | wm8731_write(PDCTRL, wm8731_regs[PDCTRL]); | 163 | wm8731_clear(PDCTRL, PDCTRL_DACPD | PDCTRL_POWEROFF); |
154 | 164 | ||
155 | /* 3) Set required values in all other registers except 12h (Active). */ | 165 | /* 3) Set required values in all other registers except 12h (Active). */ |
156 | wmcodec_write(AINTFCE, AINTFCE_FORMAT_I2S | AINTFCE_IWL_16BIT | | 166 | wm8731_write(AINTFCE, |
157 | #ifdef CODEC_SLAVE | 167 | #ifndef CODEC_SLAVE |
158 | 0); | 168 | AINTFCE_MS | |
159 | #else | ||
160 | AINTFCE_MS); | ||
161 | #endif | 169 | #endif |
162 | wm8731_write(AAPCTRL, wm8731_regs[AAPCTRL]); | 170 | AINTFCE_FORMAT_I2S | AINTFCE_IWL_16BIT); |
163 | wm8731_write(DAPCTRL, wm8731_regs[DAPCTRL]); | 171 | |
164 | wmcodec_write(SAMPCTRL, WM8731_USB24_44100HZ); | 172 | wm8731_set(AAPCTRL, AAPCTRL_DACSEL); |
173 | wm8731_write(SAMPCTRL, WM8731_USB24_44100HZ); | ||
165 | 174 | ||
166 | /* 5) The last write of the sequence should be setting OUTPD to '0' | 175 | /* 5) The last write of the sequence should be setting OUTPD to '0' |
167 | * (active) in register 0Ch, enabling the DAC signal path, free | 176 | * (active) in register 0Ch, enabling the DAC signal path, free |
168 | * of any significant power-up noise. */ | 177 | * of any significant power-up noise. */ |
169 | wm8731_write_and(PDCTRL, ~PDCTRL_OUTPD); | 178 | wm8731_clear(PDCTRL, PDCTRL_OUTPD); |
170 | } | 179 | } |
171 | 180 | ||
172 | void audiohw_postinit(void) | 181 | void audiohw_postinit(void) |
@@ -180,7 +189,7 @@ void audiohw_postinit(void) | |||
180 | 189 | ||
181 | #if defined(IRIVER_H10) || defined(IRIVER_H10_5GB) | 190 | #if defined(IRIVER_H10) || defined(IRIVER_H10_5GB) |
182 | /* We need to enable bit 4 of GPIOL for output for sound on H10 */ | 191 | /* We need to enable bit 4 of GPIOL for output for sound on H10 */ |
183 | GPIOL_OUTPUT_VAL |= 0x10; | 192 | GPIO_SET_BITWISE(GPIOL_OUTPUT_VAL, 0x10); |
184 | #endif | 193 | #endif |
185 | } | 194 | } |
186 | 195 | ||
@@ -191,8 +200,8 @@ void audiohw_set_master_vol(int vol_l, int vol_r) | |||
191 | /* 1111001 == 0dB */ | 200 | /* 1111001 == 0dB */ |
192 | /* 0110000 == -73dB */ | 201 | /* 0110000 == -73dB */ |
193 | /* 0101111 == mute (0x2f) */ | 202 | /* 0101111 == mute (0x2f) */ |
194 | wm8731_write(LOUTVOL, LOUTVOL_LZCEN | (vol_l & LOUTVOL_LHPVOL_MASK)); | 203 | wm8731_write_masked(LOUTVOL, vol_l, LOUTVOL_LHPVOL_MASK); |
195 | wm8731_write(ROUTVOL, ROUTVOL_RZCEN | (vol_r & ROUTVOL_RHPVOL_MASK)); | 204 | wm8731_write_masked(ROUTVOL, vol_r, ROUTVOL_RHPVOL_MASK); |
196 | } | 205 | } |
197 | 206 | ||
198 | /* Nice shutdown of WM8731 codec */ | 207 | /* Nice shutdown of WM8731 codec */ |
@@ -200,13 +209,14 @@ void audiohw_close(void) | |||
200 | { | 209 | { |
201 | /* POWER DOWN SEQUENCE */ | 210 | /* POWER DOWN SEQUENCE */ |
202 | /* 1) Set the OUTPD bit to '1' (power down). */ | 211 | /* 1) Set the OUTPD bit to '1' (power down). */ |
203 | wm8731_write_or(PDCTRL, PDCTRL_OUTPD); | 212 | wm8731_set(PDCTRL, PDCTRL_OUTPD); |
204 | /* 2) Remove the WM8731 supplies. */ | 213 | /* 2) Remove the WM8731 supplies. */ |
205 | } | 214 | } |
206 | 215 | ||
207 | void audiohw_set_sample_rate(int sampling_control) | 216 | void audiohw_set_sample_rate(int sampling_control) |
208 | { | 217 | { |
209 | int rate = 0; | 218 | int rate = 0; |
219 | |||
210 | switch(sampling_control) | 220 | switch(sampling_control) |
211 | { | 221 | { |
212 | case SAMPR_96: | 222 | case SAMPR_96: |
@@ -228,44 +238,44 @@ void audiohw_set_sample_rate(int sampling_control) | |||
228 | rate = WM8731_USB24_8000HZ; | 238 | rate = WM8731_USB24_8000HZ; |
229 | break; | 239 | break; |
230 | } | 240 | } |
241 | |||
231 | codec_set_active(false); | 242 | codec_set_active(false); |
232 | wmcodec_write(SAMPCTRL, rate); | 243 | wm8731_write(SAMPCTRL, rate); |
233 | codec_set_active(true); | 244 | codec_set_active(true); |
234 | } | 245 | } |
235 | 246 | ||
236 | #ifdef HAVE_RECORDING | 247 | #ifdef HAVE_RECORDING |
237 | void audiohw_enable_recording(bool source_mic) | 248 | void audiohw_enable_recording(bool source_mic) |
238 | { | 249 | { |
239 | codec_set_active(false); | ||
240 | |||
241 | wm8731_regs[PDCTRL] &= ~PDCTRL_ADCPD; | ||
242 | /* NOTE: When switching to digital monitoring we will not want | 250 | /* NOTE: When switching to digital monitoring we will not want |
243 | * the DAC disabled. */ | 251 | * the DAC disabled. */ |
244 | wm8731_regs[PDCTRL] |= PDCTRL_DACPD; | 252 | |
245 | wm8731_regs[AAPCTRL] &= ~AAPCTRL_DACSEL; | 253 | codec_set_active(false); |
246 | 254 | ||
247 | if (source_mic) { | 255 | if (source_mic) { |
248 | wm8731_write_or(LINVOL, LINVOL_LINMUTE); | 256 | wm8731_set(LINVOL, LINVOL_LINMUTE); |
249 | wm8731_write_or(RINVOL, RINVOL_RINMUTE); | 257 | wm8731_set(RINVOL, RINVOL_RINMUTE); |
250 | wm8731_regs[PDCTRL] &= ~PDCTRL_MICPD; | 258 | |
251 | wm8731_regs[PDCTRL] |= PDCTRL_LINEINPD; | 259 | wm8731_write_masked(PDCTRL, PDCTRL_LINEINPD | PDCTRL_DACPD, |
252 | wm8731_regs[AAPCTRL] |= AAPCTRL_INSEL | AAPCTRL_SIDETONE; | 260 | PDCTRL_LINEINPD | PDCTRL_MICPD | |
253 | wm8731_regs[AAPCTRL] &= ~(AAPCTRL_MUTEMIC | AAPCTRL_BYPASS); | 261 | PDCTRL_ADCPD | PDCTRL_DACPD); |
262 | wm8731_write_masked(AAPCTRL, AAPCTRL_INSEL | AAPCTRL_SIDETONE, | ||
263 | AAPCTRL_MUTEMIC | AAPCTRL_INSEL | | ||
264 | AAPCTRL_BYPASS | AAPCTRL_DACSEL | | ||
265 | AAPCTRL_SIDETONE); | ||
254 | } else { | 266 | } else { |
255 | wm8731_regs[PDCTRL] |= PDCTRL_MICPD; | 267 | wm8731_write_masked(PDCTRL, PDCTRL_MICPD | PDCTRL_DACPD, |
256 | wm8731_regs[PDCTRL] &= ~PDCTRL_LINEINPD; | 268 | PDCTRL_LINEINPD | PDCTRL_MICPD | |
257 | wm8731_regs[AAPCTRL] |= AAPCTRL_MUTEMIC | AAPCTRL_BYPASS; | 269 | PDCTRL_ADCPD | PDCTRL_DACPD); |
258 | wm8731_regs[AAPCTRL] &= ~(AAPCTRL_INSEL | AAPCTRL_SIDETONE); | 270 | wm8731_write_masked(AAPCTRL, AAPCTRL_MUTEMIC | AAPCTRL_BYPASS, |
271 | AAPCTRL_MUTEMIC | AAPCTRL_INSEL | | ||
272 | AAPCTRL_BYPASS | AAPCTRL_DACSEL | | ||
273 | AAPCTRL_SIDETONE); | ||
274 | |||
275 | wm8731_clear(LINVOL, LINVOL_LINMUTE); | ||
276 | wm8731_clear(RINVOL, RINVOL_RINMUTE); | ||
259 | } | 277 | } |
260 | 278 | ||
261 | wm8731_write(PDCTRL, wm8731_regs[PDCTRL]); | ||
262 | wm8731_write(AAPCTRL, wm8731_regs[AAPCTRL]); | ||
263 | |||
264 | if (!source_mic) { | ||
265 | wm8731_write_and(LINVOL, ~LINVOL_LINMUTE); | ||
266 | wm8731_write_and(RINVOL, ~RINVOL_RINMUTE); | ||
267 | } | ||
268 | |||
269 | codec_set_active(true); | 279 | codec_set_active(true); |
270 | } | 280 | } |
271 | 281 | ||
@@ -273,23 +283,22 @@ void audiohw_disable_recording(void) | |||
273 | { | 283 | { |
274 | codec_set_active(false); | 284 | codec_set_active(false); |
275 | 285 | ||
276 | /* Mute inputs */ | 286 | /* Mute line inputs */ |
277 | wm8731_write_or(LINVOL, LINVOL_LINMUTE); | 287 | wm8731_set(LINVOL, LINVOL_LINMUTE); |
278 | wm8731_write_or(RINVOL, RINVOL_RINMUTE); | 288 | wm8731_set(RINVOL, RINVOL_RINMUTE); |
279 | wm8731_write_or(AAPCTRL, AAPCTRL_MUTEMIC); | 289 | wm8731_set(AAPCTRL, AAPCTRL_MUTEMIC); |
280 | 290 | ||
281 | /* Turn off input analog audio paths */ | 291 | /* Turn off input analog audio paths */ |
282 | wm8731_regs[AAPCTRL] &= ~(AAPCTRL_BYPASS | AAPCTRL_SIDETONE); | 292 | wm8731_clear(AAPCTRL, AAPCTRL_BYPASS | AAPCTRL_SIDETONE); |
283 | wm8731_write(AAPCTRL, wm8731_regs[AAPCTRL]); | ||
284 | 293 | ||
285 | /* Set power config */ | 294 | /* Set power config */ |
286 | wm8731_regs[PDCTRL] &= ~PDCTRL_DACPD; | 295 | wm8731_write_masked(PDCTRL, |
287 | wm8731_regs[PDCTRL] |= PDCTRL_MICPD | PDCTRL_LINEINPD | | 296 | PDCTRL_LINEINPD | PDCTRL_MICPD | PDCTRL_ADCPD, |
288 | PDCTRL_ADCPD; | 297 | PDCTRL_LINEINPD | PDCTRL_MICPD | PDCTRL_DACPD | |
289 | wm8731_write(PDCTRL, wm8731_regs[PDCTRL]); | 298 | PDCTRL_ADCPD); |
290 | 299 | ||
291 | /* Select DAC */ | 300 | /* Select DAC */ |
292 | wm8731_write_or(AAPCTRL, AAPCTRL_DACSEL); | 301 | wm8731_set(AAPCTRL, AAPCTRL_DACSEL); |
293 | 302 | ||
294 | codec_set_active(true); | 303 | codec_set_active(true); |
295 | } | 304 | } |
@@ -300,17 +309,15 @@ void audiohw_set_recvol(int left, int right, int type) | |||
300 | { | 309 | { |
301 | case AUDIO_GAIN_MIC: | 310 | case AUDIO_GAIN_MIC: |
302 | if (left > 0) { | 311 | if (left > 0) { |
303 | wm8731_write_or(AAPCTRL, AAPCTRL_MIC_BOOST); | 312 | wm8731_set(AAPCTRL, AAPCTRL_MIC_BOOST); |
304 | } | 313 | } |
305 | else { | 314 | else { |
306 | wm8731_write_and(AAPCTRL, ~AAPCTRL_MIC_BOOST); | 315 | wm8731_clear(AAPCTRL, AAPCTRL_MIC_BOOST); |
307 | } | 316 | } |
308 | break; | 317 | break; |
309 | case AUDIO_GAIN_LINEIN: | 318 | case AUDIO_GAIN_LINEIN: |
310 | wm8731_regs[LINVOL] &= ~LINVOL_MASK; | 319 | wm8731_write_masked(LINVOL, left, LINVOL_MASK); |
311 | wm8731_write(LINVOL, wm8731_regs[LINVOL] | (left & LINVOL_MASK)); | 320 | wm8731_write_masked(RINVOL, right, RINVOL_MASK); |
312 | wm8731_regs[RINVOL] &= ~RINVOL_MASK; | ||
313 | wm8731_write(RINVOL, wm8731_regs[RINVOL] | (right & RINVOL_MASK)); | ||
314 | break; | 321 | break; |
315 | default: | 322 | default: |
316 | return; | 323 | return; |
@@ -319,14 +326,13 @@ void audiohw_set_recvol(int left, int right, int type) | |||
319 | 326 | ||
320 | void audiohw_set_monitor(bool enable) | 327 | void audiohw_set_monitor(bool enable) |
321 | { | 328 | { |
322 | if(enable) | 329 | if(enable) { |
323 | { | 330 | wm8731_clear(PDCTRL, PDCTRL_LINEINPD); |
324 | wm8731_write_and(PDCTRL, ~PDCTRL_LINEINPD); | 331 | wm8731_set(AAPCTRL, AAPCTRL_BYPASS); |
325 | wm8731_write_or(AAPCTRL, AAPCTRL_BYPASS); | ||
326 | } | 332 | } |
327 | else { | 333 | else { |
328 | wm8731_write_and(AAPCTRL, ~AAPCTRL_BYPASS); | 334 | wm8731_clear(AAPCTRL, AAPCTRL_BYPASS); |
329 | wm8731_write_or(PDCTRL, PDCTRL_LINEINPD); | 335 | wm8731_set(PDCTRL, PDCTRL_LINEINPD); |
330 | } | 336 | } |
331 | } | 337 | } |
332 | #endif /* HAVE_RECORDING */ | 338 | #endif /* HAVE_RECORDING */ |
diff --git a/firmware/export/wm8731.h b/firmware/export/wm8731.h index a572546e95..2ea479fff7 100644 --- a/firmware/export/wm8731.h +++ b/firmware/export/wm8731.h | |||
@@ -122,6 +122,8 @@ extern void audiohw_set_sample_rate(int sampling_control); | |||
122 | #define RESET 0x0f | 122 | #define RESET 0x0f |
123 | #define RESET_RESET 0x0 | 123 | #define RESET_RESET 0x0 |
124 | 124 | ||
125 | #define WM8731_NUM_REGS 0x0a /* RESET not included */ | ||
126 | |||
125 | /* SAMPCTRL values for the supported samplerates (24MHz MCLK/USB): */ | 127 | /* SAMPCTRL values for the supported samplerates (24MHz MCLK/USB): */ |
126 | #define WM8731_USB24_8000HZ 0x4d | 128 | #define WM8731_USB24_8000HZ 0x4d |
127 | #define WM8731_USB24_32000HZ 0x59 | 129 | #define WM8731_USB24_32000HZ 0x59 |