diff options
Diffstat (limited to 'firmware/drivers/audio')
-rw-r--r-- | firmware/drivers/audio/wm8751.c | 175 |
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) | ||
103 | static 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 | ||
102 | static void audiohw_mute(bool mute) | 114 | static 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) | ||
285 | void 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 */ | ||
439 | void 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 | ||