summaryrefslogtreecommitdiff
path: root/firmware/drivers/audio/wm8751.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/drivers/audio/wm8751.c')
-rw-r--r--firmware/drivers/audio/wm8751.c153
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
116static void audiohw_mute(bool mute) 124static 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 */
279void audiohw_set_frequency(int fsel) 288void 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 */
308void 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
299void audiohw_set_recsrc(int source, bool recording) 320void 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 */
453void audiohw_set_recvol(int left, int right, int type) 505void 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 */