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.c175
1 files changed, 175 insertions, 0 deletions
diff --git a/firmware/drivers/audio/wm8751.c b/firmware/drivers/audio/wm8751.c
index ffe7f20bba..18441826d4 100644
--- a/firmware/drivers/audio/wm8751.c
+++ b/firmware/drivers/audio/wm8751.c
@@ -99,6 +99,18 @@ static int adaptivebass2hw(int value)
99} 99}
100#endif 100#endif
101 101
102#if defined(HAVE_WM8750)
103static int recvol2hw(int value)
104{
105/* convert tenth of dB of input volume (-172...300) to input register value */
106 /* +30dB to -17.25 0.75dB step 6 bits */
107 /* 111111 == +30dB (0x3f) */
108 /* 010111 == 0dB (0x17) */
109 /* 000000 == -17.25dB */
110
111 return (3*(value/10 - 0x17))/4;
112}
113#endif
102static void audiohw_mute(bool mute) 114static void audiohw_mute(bool mute)
103{ 115{
104 /* Mute: Set DACMU = 1 to soft-mute the audio DACs. */ 116 /* Mute: Set DACMU = 1 to soft-mute the audio DACs. */
@@ -268,3 +280,166 @@ void audiohw_set_frequency(int fsel)
268 wmcodec_write(CLOCKING, srctrl_table[fsel]); 280 wmcodec_write(CLOCKING, srctrl_table[fsel]);
269#endif 281#endif
270} 282}
283
284#if defined(HAVE_WM8750)
285void audiohw_set_recsrc(int source, bool recording)
286{
287 /* INPUT1 - FM radio
288 * INPUT2 - Line-in
289 * INPUT3 - MIC
290 *
291 * if recording == false we use analog bypass from input
292 * turn off ADC, PGA to save power
293 * turn on output buffer(s)
294 *
295 * if recording == true we route input signal to PGA
296 * and monitoring picks up signal after PGA in analog domain
297 * turn on ADC, PGA, DAC, output buffer(s)
298 */
299
300 switch(source)
301 {
302 case AUDIO_SRC_PLAYBACK:
303 /* mute PGA, disable all audio paths but DAC and output stage*/
304 wmcodec_write(LINVOL, LINVOL_LINMUTE | LINVOL_LINVOL(23)); /* 0dB */
305 wmcodec_write(RINVOL, RINVOL_RINMUTE | RINVOL_RINVOL(23)); /* 0dB */
306 wmcodec_write(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_50K);
307 wmcodec_write(PWRMGMT2, PWRMGMT2_DACL | PWRMGMT2_DACR |
308 PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1);
309
310 /* route DAC signal to output mixer */
311 wmcodec_write(LEFTMIX1, LEFTMIX1_LD2LO);
312 wmcodec_write(RIGHTMIX2, RIGHTMIX2_RD2RO);
313
314 /* unmute DAC */
315 audiohw_mute(false);
316 break;
317
318 case AUDIO_SRC_FMRADIO:
319 if(recording)
320 {
321 /* Set input volume to PGA */
322 wmcodec_write(LINVOL, LINVOL_LINVOL(23));
323 wmcodec_write(RINVOL, RINVOL_RINVOL(23));
324
325 /* Turn on PGA and ADC */
326 wmcodec_write(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_50K |
327 PWRMGMT1_AINL | PWRMGMT1_AINR |
328 PWRMGMT1_ADCL | PWRMGMT1_ADCR);
329
330 /* Setup input source for PGA as INPUT1
331 * MICBOOST disabled
332 */
333 wmcodec_write(ADCL, ADCL_LINSEL_LINPUT1 | ADCL_LMICBOOST_DISABLED);
334 wmcodec_write(ADCR, ADCR_RINSEL_RINPUT1 | ADCR_RMICBOOST_DISABLED);
335
336 /* setup output digital data
337 * default is LADC -> LDATA, RADC -> RDATA
338 * so we don't touch this
339 */
340
341 /* power up DAC and output stage */
342 wmcodec_write(PWRMGMT2, PWRMGMT2_DACL | PWRMGMT2_DACR |
343 PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1);
344
345 /* analog monitor */
346 wmcodec_write(LEFTMIX1, LEFTMIX1_LMIXSEL_ADCLIN |
347 LEFTMIX1_LD2LO);
348 wmcodec_write(RIGHTMIX2, RIGHTMIX2_RMIXSEL_ADCRIN |
349 RIGHTMIX2_RD2RO);
350 }
351 else
352 {
353
354 /* turn off ADC, PGA */
355 wmcodec_write(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_50K);
356
357 /* turn on DAC and output stage */
358 wmcodec_write(PWRMGMT2, PWRMGMT2_DACL | PWRMGMT2_DACR |
359 PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1);
360
361 /* setup monitor mode by routing input signal to outmix
362 * at 0dB volume
363 */
364 wmcodec_write(LEFTMIX1, LEFTMIX1_LI2LO | LEFTMIX1_LMIXSEL_LINPUT1 |
365 LEFTMIX1_LI2LOVOL(0x20) | LEFTMIX1_LD2LO);
366 wmcodec_write(RIGHTMIX2, RIGHTMIX2_RI2RO | RIGHTMIX2_RMIXSEL_RINPUT1 |
367 RIGHTMIX2_RI2ROVOL(0x20) | RIGHTMIX2_RD2RO);
368 }
369 break;
370
371 case AUDIO_SRC_LINEIN:
372 /* Set input volume to PGA */
373 wmcodec_write(LINVOL, LINVOL_LINVOL(23));
374 wmcodec_write(RINVOL, RINVOL_RINVOL(23));
375
376 /* Turn on PGA, ADC, DAC */
377 wmcodec_write(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_50K |
378 PWRMGMT1_AINL | PWRMGMT1_AINR |
379 PWRMGMT1_ADCL | PWRMGMT1_ADCR);
380
381 /* turn on DAC and output stage */
382 wmcodec_write(PWRMGMT2, PWRMGMT2_DACL | PWRMGMT2_DACR |
383 PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1);
384
385 /* Setup input source for PGA as INPUT2
386 * MICBOOST disabled
387 */
388 wmcodec_write(ADCL, ADCL_LINSEL_LINPUT2 | ADCL_LMICBOOST_DISABLED);
389 wmcodec_write(ADCR, ADCR_RINSEL_RINPUT2 | ADCR_RMICBOOST_DISABLED);
390
391 /* setup output digital data
392 * default is LADC -> LDATA, RADC -> RDATA
393 * so we don't touch this
394 */
395
396 /* digital monitor */
397 wmcodec_write(LEFTMIX1, LEFTMIX1_LMIXSEL_ADCLIN |
398 LEFTMIX1_LD2LO);
399 wmcodec_write(RIGHTMIX2, RIGHTMIX2_RMIXSEL_ADCRIN |
400 RIGHTMIX2_RD2RO);
401 break;
402
403 case AUDIO_SRC_MIC:
404 /* Set input volume to PGA */
405 wmcodec_write(LINVOL, LINVOL_LINVOL(23));
406 wmcodec_write(RINVOL, RINVOL_RINVOL(23));
407
408 /* Turn on PGA and ADC, turn off DAC */
409 wmcodec_write(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_50K |
410 PWRMGMT1_AINL | PWRMGMT1_AINR |
411 PWRMGMT1_ADCL | PWRMGMT1_ADCR);
412
413 /* turn on DAC and output stage */
414 wmcodec_write(PWRMGMT2, PWRMGMT2_DACL | PWRMGMT2_DACR |
415 PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1);
416
417 /* Setup input source for PGA as INPUT3
418 * MICBOOST disabled
419 */
420 wmcodec_write(ADCL, ADCL_LINSEL_LINPUT3 | ADCL_LMICBOOST_DISABLED);
421 wmcodec_write(ADCR, ADCR_RINSEL_RINPUT3 | ADCR_RMICBOOST_DISABLED);
422
423 /* setup output digital data
424 * default is LADC -> LDATA, RADC -> RDATA
425 * so we don't touch this
426 */
427
428 /* analog monitor */
429 wmcodec_write(LEFTMIX1, LEFTMIX1_LMIXSEL_ADCLIN |
430 LEFTMIX1_LD2LO);
431 wmcodec_write(RIGHTMIX2, RIGHTMIX2_RMIXSEL_ADCRIN |
432 RIGHTMIX2_RD2RO);
433 break;
434
435 } /* switch(source) */
436}
437
438/* Setup PGA gain */
439void audiohw_set_recvol(int left, int right, int type)
440{
441 (void)type;
442 wmcodec_write(LINVOL, LINVOL_LINVOL(recvol2hw(left)));
443 wmcodec_write(RINVOL, RINVOL_RINVOL(recvol2hw(right)));
444}
445#endif