diff options
author | Marcin Bukat <marcin.bukat@gmail.com> | 2010-07-02 21:09:28 +0000 |
---|---|---|
committer | Marcin Bukat <marcin.bukat@gmail.com> | 2010-07-02 21:09:28 +0000 |
commit | 971a6e9c9480d07b939f5e80a050ef9f49c89f81 (patch) | |
tree | e01d1843ceb6e4c3efb5a9de7a2b862eb368a461 /firmware/drivers/audio/wm8751.c | |
parent | 15d0ac01345346ae348bb15c58ddf88ef0ac0020 (diff) | |
download | rockbox-971a6e9c9480d07b939f5e80a050ef9f49c89f81.tar.gz rockbox-971a6e9c9480d07b939f5e80a050ef9f49c89f81.zip |
HD200 - Setup codec as I2S master and enable recording
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27250 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/drivers/audio/wm8751.c')
-rw-r--r-- | firmware/drivers/audio/wm8751.c | 153 |
1 files changed, 103 insertions, 50 deletions
diff --git a/firmware/drivers/audio/wm8751.c b/firmware/drivers/audio/wm8751.c index 2adbdcaa56..6e37a91ed7 100644 --- a/firmware/drivers/audio/wm8751.c +++ b/firmware/drivers/audio/wm8751.c | |||
@@ -42,6 +42,14 @@ const struct sound_settings_info audiohw_settings[] = { | |||
42 | [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0}, | 42 | [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0}, |
43 | [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0}, | 43 | [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0}, |
44 | [SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100}, | 44 | [SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100}, |
45 | #ifdef AUDIOHW_HAVE_DEPTH_3D | ||
46 | [SOUND_DEPTH_3D] = {"", 0, 1, 0, 15, 0}, | ||
47 | #endif | ||
48 | #ifdef HAVE_RECORDING | ||
49 | [SOUND_LEFT_GAIN] = {"dB", 1, 1,-172, 300, 0}, | ||
50 | [SOUND_RIGHT_GAIN] = {"dB", 1, 1,-172, 300, 0}, | ||
51 | [SOUND_MIC_GAIN] = {"dB", 1, 1,-172, 300, 0}, | ||
52 | #endif | ||
45 | }; | 53 | }; |
46 | 54 | ||
47 | /* Flags used in combination with settings */ | 55 | /* Flags used in combination with settings */ |
@@ -110,7 +118,7 @@ static int recvol2hw(int value) | |||
110 | /* 010111 == 0dB (0x17) */ | 118 | /* 010111 == 0dB (0x17) */ |
111 | /* 000000 == -17.25dB */ | 119 | /* 000000 == -17.25dB */ |
112 | 120 | ||
113 | return (3*(value/10 - 0x17))/4; | 121 | return ((4*(value))/30 + 0x17); |
114 | } | 122 | } |
115 | #endif | 123 | #endif |
116 | static void audiohw_mute(bool mute) | 124 | static void audiohw_mute(bool mute) |
@@ -167,6 +175,14 @@ void audiohw_postinit(void) | |||
167 | 175 | ||
168 | /* 4. Enable line and / or headphone output buffers as required. */ | 176 | /* 4. Enable line and / or headphone output buffers as required. */ |
169 | #if defined(MROBE_100) || defined(MPIO_HD200) | 177 | #if defined(MROBE_100) || defined(MPIO_HD200) |
178 | /* fix for high pitch noise after power-up on HD200 | ||
179 | * it is *NOT* required step according to the | ||
180 | * Datasheet for WM8750L but real life is different :-) | ||
181 | */ | ||
182 | wmcodec_write(LOUT1, LOUT1_BITS); | ||
183 | wmcodec_write(ROUT1, ROUT1_BITS); | ||
184 | |||
185 | /* power-up output stage */ | ||
170 | wmcodec_write(PWRMGMT2, PWRMGMT2_DACL | PWRMGMT2_DACR | | 186 | wmcodec_write(PWRMGMT2, PWRMGMT2_DACL | PWRMGMT2_DACR | |
171 | PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1); | 187 | PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1); |
172 | #else | 188 | #else |
@@ -196,16 +212,6 @@ void audiohw_postinit(void) | |||
196 | #endif | 212 | #endif |
197 | #endif | 213 | #endif |
198 | 214 | ||
199 | #ifdef MPIO_HD200 | ||
200 | /* Crude fix for high pitch noise at startup | ||
201 | * I should find out what realy causes this | ||
202 | */ | ||
203 | wmcodec_write(LOUT1, LOUT1_BITS|0x7f); | ||
204 | wmcodec_write(ROUT1, ROUT1_BITS|0x7f); | ||
205 | wmcodec_write(LOUT1, LOUT1_BITS); | ||
206 | wmcodec_write(ROUT1, ROUT1_BITS); | ||
207 | #endif | ||
208 | |||
209 | /* lower power consumption */ | 215 | /* lower power consumption */ |
210 | wmcodec_write(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_50K); | 216 | wmcodec_write(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_50K); |
211 | 217 | ||
@@ -276,10 +282,12 @@ void audiohw_close(void) | |||
276 | wmcodec_write(PWRMGMT1, 0x0); | 282 | wmcodec_write(PWRMGMT1, 0x0); |
277 | } | 283 | } |
278 | 284 | ||
285 | /* According to datasheet of WM8750 | ||
286 | * clocking setup is needed in both slave and master mode | ||
287 | */ | ||
279 | void audiohw_set_frequency(int fsel) | 288 | void audiohw_set_frequency(int fsel) |
280 | { | 289 | { |
281 | (void)fsel; | 290 | (void)fsel; |
282 | #ifndef CODEC_SLAVE | ||
283 | static const unsigned char srctrl_table[HW_NUM_FREQ] = | 291 | static const unsigned char srctrl_table[HW_NUM_FREQ] = |
284 | { | 292 | { |
285 | HW_HAVE_11_([HW_FREQ_11] = CODEC_SRCTRL_11025HZ,) | 293 | HW_HAVE_11_([HW_FREQ_11] = CODEC_SRCTRL_11025HZ,) |
@@ -292,10 +300,23 @@ void audiohw_set_frequency(int fsel) | |||
292 | fsel = HW_FREQ_DEFAULT; | 300 | fsel = HW_FREQ_DEFAULT; |
293 | 301 | ||
294 | wmcodec_write(CLOCKING, srctrl_table[fsel]); | 302 | wmcodec_write(CLOCKING, srctrl_table[fsel]); |
295 | #endif | ||
296 | } | 303 | } |
297 | 304 | ||
298 | #if defined(HAVE_WM8750) | 305 | #if defined(HAVE_WM8750) |
306 | #ifdef AUDIOHW_HAVE_DEPTH_3D | ||
307 | /* Set the depth of the 3D effect */ | ||
308 | void audiohw_set_depth_3d(int val) | ||
309 | { | ||
310 | if (val) | ||
311 | wmcodec_write(ENHANCE_3D, | ||
312 | ENHANCE_3D_MODE3D_PLAYBACK | ENHANCE_3D_DEPTH(val) | | ||
313 | ENHANCE_3D_3DEN); | ||
314 | else | ||
315 | wmcodec_write(ENHANCE_3D,ENHANCE_3D_MODE3D_PLAYBACK); | ||
316 | } | ||
317 | #endif | ||
318 | |||
319 | #ifdef HAVE_RECORDING | ||
299 | void audiohw_set_recsrc(int source, bool recording) | 320 | void audiohw_set_recsrc(int source, bool recording) |
300 | { | 321 | { |
301 | /* INPUT1 - FM radio | 322 | /* INPUT1 - FM radio |
@@ -307,17 +328,30 @@ void audiohw_set_recsrc(int source, bool recording) | |||
307 | * turn on output buffer(s) | 328 | * turn on output buffer(s) |
308 | * | 329 | * |
309 | * if recording == true we route input signal to PGA | 330 | * if recording == true we route input signal to PGA |
310 | * and monitoring picks up signal after PGA in analog domain | 331 | * and monitoring picks up signal after PGA and ADC |
311 | * turn on ADC, PGA, DAC, output buffer(s) | 332 | * turn on ADC, PGA, DAC, output buffer(s) |
312 | */ | 333 | */ |
313 | 334 | ||
314 | switch(source) | 335 | switch(source) |
315 | { | 336 | { |
316 | case AUDIO_SRC_PLAYBACK: | 337 | case AUDIO_SRC_PLAYBACK: |
317 | /* mute PGA, disable all audio paths but DAC and output stage*/ | 338 | /* turn off DAC and ADC in order to setup Enchance 3D function |
318 | wmcodec_write(LINVOL, LINVOL_LINMUTE | LINVOL_LINVOL(23)); /* 0dB */ | 339 | * for playback. This does not turn on enchancement but |
319 | wmcodec_write(RINVOL, RINVOL_RINMUTE | RINVOL_RINVOL(23)); /* 0dB */ | 340 | * the switch between playback/record has to be done with |
341 | * DAC and ADC off | ||
342 | */ | ||
343 | #ifdef AUDIOHW_HAVE_DEPTH_3D | ||
320 | wmcodec_write(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_50K); | 344 | wmcodec_write(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_50K); |
345 | wmcodec_write(PWRMGMT2, 0x00); | ||
346 | wmcodec_write(ENHANCE_3D, ENHANCE_3D_MODE3D_PLAYBACK); | ||
347 | #endif | ||
348 | /* mute PGA, disable all audio paths but DAC and output stage*/ | ||
349 | wmcodec_write(LINVOL, LINVOL_LINMUTE | LINVOL_LINVOL(0x17)); /* 0dB */ | ||
350 | wmcodec_write(RINVOL, RINVOL_RINMUTE | RINVOL_RINVOL(0x17)); /* 0dB */ | ||
351 | |||
352 | wmcodec_write(LOUT1, LOUT1_BITS); | ||
353 | wmcodec_write(ROUT1, ROUT1_BITS); | ||
354 | |||
321 | wmcodec_write(PWRMGMT2, PWRMGMT2_DACL | PWRMGMT2_DACR | | 355 | wmcodec_write(PWRMGMT2, PWRMGMT2_DACL | PWRMGMT2_DACR | |
322 | PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1); | 356 | PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1); |
323 | 357 | ||
@@ -332,15 +366,26 @@ void audiohw_set_recsrc(int source, bool recording) | |||
332 | case AUDIO_SRC_FMRADIO: | 366 | case AUDIO_SRC_FMRADIO: |
333 | if(recording) | 367 | if(recording) |
334 | { | 368 | { |
335 | /* Set input volume to PGA */ | 369 | /* turn off DAC and ADC in order to setup Enchance 3D function |
336 | wmcodec_write(LINVOL, LINVOL_LINVOL(23)); | 370 | * for playback. This does not turn on enchancement but |
337 | wmcodec_write(RINVOL, RINVOL_RINVOL(23)); | 371 | * the switch between playback/record has to be done with |
372 | * DAC and ADC off | ||
373 | */ | ||
374 | #ifdef AUDIOHW_HAVE_DEPTH_3D | ||
375 | wmcodec_write(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_50K); | ||
376 | wmcodec_write(PWRMGMT2, 0x00); | ||
377 | wmcodec_write(ENHANCE_3D, ENHANCE_3D_MODE3D_RECORD); | ||
378 | #endif | ||
338 | 379 | ||
339 | /* Turn on PGA and ADC */ | 380 | /* Turn on PGA and ADC */ |
340 | wmcodec_write(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_50K | | 381 | wmcodec_write(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_50K | |
341 | PWRMGMT1_AINL | PWRMGMT1_AINR | | 382 | PWRMGMT1_AINL | PWRMGMT1_AINR | |
342 | PWRMGMT1_ADCL | PWRMGMT1_ADCR); | 383 | PWRMGMT1_ADCL | PWRMGMT1_ADCR); |
343 | 384 | ||
385 | /* Set input volume to PGA 0dB*/ | ||
386 | wmcodec_write(LINVOL, LINVOL_LIVU|LINVOL_LINVOL(0x17)); | ||
387 | wmcodec_write(RINVOL, RINVOL_RIVU|RINVOL_RINVOL(0x17)); | ||
388 | |||
344 | /* Setup input source for PGA as INPUT1 | 389 | /* Setup input source for PGA as INPUT1 |
345 | * MICBOOST disabled | 390 | * MICBOOST disabled |
346 | */ | 391 | */ |
@@ -356,38 +401,45 @@ void audiohw_set_recsrc(int source, bool recording) | |||
356 | wmcodec_write(PWRMGMT2, PWRMGMT2_DACL | PWRMGMT2_DACR | | 401 | wmcodec_write(PWRMGMT2, PWRMGMT2_DACL | PWRMGMT2_DACR | |
357 | PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1); | 402 | PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1); |
358 | 403 | ||
359 | /* analog monitor */ | 404 | /* route DAC signal to output mixer */ |
360 | wmcodec_write(LEFTMIX1, LEFTMIX1_LMIXSEL_ADCLIN | | 405 | wmcodec_write(LEFTMIX1, LEFTMIX1_LD2LO); |
361 | LEFTMIX1_LD2LO); | 406 | wmcodec_write(RIGHTMIX2, RIGHTMIX2_RD2RO); |
362 | wmcodec_write(RIGHTMIX2, RIGHTMIX2_RMIXSEL_ADCRIN | | ||
363 | RIGHTMIX2_RD2RO); | ||
364 | } | 407 | } |
365 | else | 408 | else |
366 | { | 409 | { |
367 | |||
368 | /* turn off ADC, PGA */ | 410 | /* turn off ADC, PGA */ |
369 | wmcodec_write(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_50K); | 411 | wmcodec_write(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_50K); |
370 | 412 | ||
413 | wmcodec_write(LOUT1, LOUT1_BITS); | ||
414 | wmcodec_write(ROUT1, ROUT1_BITS); | ||
415 | |||
371 | /* turn on DAC and output stage */ | 416 | /* turn on DAC and output stage */ |
372 | wmcodec_write(PWRMGMT2, PWRMGMT2_DACL | PWRMGMT2_DACR | | 417 | wmcodec_write(PWRMGMT2, PWRMGMT2_DACL | PWRMGMT2_DACR | |
373 | PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1); | 418 | PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1); |
374 | 419 | ||
375 | /* setup monitor mode by routing input signal to outmix | 420 | /* setup monitor mode by routing input signal to outmix |
376 | * at 0dB volume | 421 | * at 0dB volume |
377 | */ | 422 | */ |
378 | wmcodec_write(LEFTMIX1, LEFTMIX1_LI2LO | LEFTMIX1_LMIXSEL_LINPUT1 | | 423 | wmcodec_write(LEFTMIX1, LEFTMIX1_LI2LO | LEFTMIX1_LMIXSEL_LINPUT1 | |
379 | LEFTMIX1_LI2LOVOL(0x20) | LEFTMIX1_LD2LO); | 424 | LEFTMIX1_LI2LOVOL(0x20) | LEFTMIX1_LD2LO); |
380 | wmcodec_write(RIGHTMIX2, RIGHTMIX2_RI2RO | RIGHTMIX2_RMIXSEL_RINPUT1 | | 425 | wmcodec_write(RIGHTMIX1, RIGHTMIX1_RMIXSEL_RINPUT1); |
426 | wmcodec_write(RIGHTMIX2, RIGHTMIX2_RI2RO | | ||
381 | RIGHTMIX2_RI2ROVOL(0x20) | RIGHTMIX2_RD2RO); | 427 | RIGHTMIX2_RI2ROVOL(0x20) | RIGHTMIX2_RD2RO); |
382 | } | 428 | } |
383 | break; | 429 | break; |
384 | 430 | ||
385 | case AUDIO_SRC_LINEIN: | 431 | case AUDIO_SRC_LINEIN: |
432 | #ifdef AUDIOHW_HAVE_DEPTH_3D | ||
433 | wmcodec_write(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_50K); | ||
434 | wmcodec_write(PWRMGMT2, 0x00); | ||
435 | wmcodec_write(ENHANCE_3D, ENHANCE_3D_MODE3D_RECORD); | ||
436 | #endif | ||
437 | |||
386 | /* Set input volume to PGA */ | 438 | /* Set input volume to PGA */ |
387 | wmcodec_write(LINVOL, LINVOL_LINVOL(23)); | 439 | wmcodec_write(LINVOL, LINVOL_LIVU | LINVOL_LINVOL(23)); |
388 | wmcodec_write(RINVOL, RINVOL_RINVOL(23)); | 440 | wmcodec_write(RINVOL, RINVOL_RIVU | RINVOL_RINVOL(23)); |
389 | 441 | ||
390 | /* Turn on PGA, ADC, DAC */ | 442 | /* Turn on PGA, ADC */ |
391 | wmcodec_write(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_50K | | 443 | wmcodec_write(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_50K | |
392 | PWRMGMT1_AINL | PWRMGMT1_AINR | | 444 | PWRMGMT1_AINL | PWRMGMT1_AINR | |
393 | PWRMGMT1_ADCL | PWRMGMT1_ADCR); | 445 | PWRMGMT1_ADCL | PWRMGMT1_ADCR); |
@@ -406,18 +458,21 @@ void audiohw_set_recsrc(int source, bool recording) | |||
406 | * default is LADC -> LDATA, RADC -> RDATA | 458 | * default is LADC -> LDATA, RADC -> RDATA |
407 | * so we don't touch this | 459 | * so we don't touch this |
408 | */ | 460 | */ |
409 | 461 | /* route DAC signal to output mixer */ | |
410 | /* digital monitor */ | 462 | wmcodec_write(LEFTMIX1, LEFTMIX1_LD2LO); |
411 | wmcodec_write(LEFTMIX1, LEFTMIX1_LMIXSEL_ADCLIN | | 463 | wmcodec_write(RIGHTMIX2, RIGHTMIX2_RD2RO); |
412 | LEFTMIX1_LD2LO); | ||
413 | wmcodec_write(RIGHTMIX2, RIGHTMIX2_RMIXSEL_ADCRIN | | ||
414 | RIGHTMIX2_RD2RO); | ||
415 | break; | 464 | break; |
416 | 465 | ||
417 | case AUDIO_SRC_MIC: | 466 | case AUDIO_SRC_MIC: |
467 | #ifdef AUDIOHW_HAVE_DEPTH_3D | ||
468 | wmcodec_write(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_50K); | ||
469 | wmcodec_write(PWRMGMT2, 0x00); | ||
470 | wmcodec_write(ENHANCE_3D, ENHANCE_3D_MODE3D_RECORD); | ||
471 | #endif | ||
472 | |||
418 | /* Set input volume to PGA */ | 473 | /* Set input volume to PGA */ |
419 | wmcodec_write(LINVOL, LINVOL_LINVOL(23)); | 474 | wmcodec_write(LINVOL, LINVOL_LIVU | LINVOL_LINVOL(23)); |
420 | wmcodec_write(RINVOL, RINVOL_RINVOL(23)); | 475 | wmcodec_write(RINVOL, RINVOL_RIVU | RINVOL_RINVOL(23)); |
421 | 476 | ||
422 | /* Turn on PGA and ADC, turn off DAC */ | 477 | /* Turn on PGA and ADC, turn off DAC */ |
423 | wmcodec_write(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_50K | | 478 | wmcodec_write(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_50K | |
@@ -439,21 +494,19 @@ void audiohw_set_recsrc(int source, bool recording) | |||
439 | * so we don't touch this | 494 | * so we don't touch this |
440 | */ | 495 | */ |
441 | 496 | ||
442 | /* analog monitor */ | 497 | /* route DAC signal to output mixer */ |
443 | wmcodec_write(LEFTMIX1, LEFTMIX1_LMIXSEL_ADCLIN | | 498 | wmcodec_write(LEFTMIX1, LEFTMIX1_LD2LO); |
444 | LEFTMIX1_LD2LO); | 499 | wmcodec_write(RIGHTMIX2, RIGHTMIX2_RD2RO); |
445 | wmcodec_write(RIGHTMIX2, RIGHTMIX2_RMIXSEL_ADCRIN | | ||
446 | RIGHTMIX2_RD2RO); | ||
447 | break; | ||
448 | 500 | ||
449 | } /* switch(source) */ | 501 | } /* switch(source) */ |
450 | } | 502 | } |
451 | 503 | ||
452 | /* Setup PGA gain */ | 504 | /* Setup PGA gain */ |
453 | void audiohw_set_recvol(int left, int right, int type) | 505 | void audiohw_set_recvol(int vol_l, int vol_r, int type) |
454 | { | 506 | { |
455 | (void)type; | 507 | (void)type; |
456 | wmcodec_write(LINVOL, LINVOL_LINVOL(recvol2hw(left))); | 508 | wmcodec_write(LINVOL, LINVOL_LIZC|LINVOL_LINVOL(recvol2hw(vol_l))); |
457 | wmcodec_write(RINVOL, RINVOL_RINVOL(recvol2hw(right))); | 509 | wmcodec_write(RINVOL, RINVOL_RIZC|RINVOL_RIVU|RINVOL_RINVOL(recvol2hw(vol_r))); |
458 | } | 510 | } |
459 | #endif | 511 | #endif /* HAVE_RECORDING */ |
512 | #endif /* HAVE_WM8750 */ | ||