Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
wm8994.c
00001 /** 00002 ****************************************************************************** 00003 * @file wm8994.c 00004 * @author MCD Application Team 00005 * @version V2.0.0 00006 * @date 24-June-2015 00007 * @brief This file provides the WM8994 Audio Codec driver. 00008 ****************************************************************************** 00009 * @attention 00010 * 00011 * <h2><center>© COPYRIGHT(c) 2015 STMicroelectronics</center></h2> 00012 * 00013 * Redistribution and use in source and binary forms, with or without modification, 00014 * are permitted provided that the following conditions are met: 00015 * 1. Redistributions of source code must retain the above copyright notice, 00016 * this list of conditions and the following disclaimer. 00017 * 2. Redistributions in binary form must reproduce the above copyright notice, 00018 * this list of conditions and the following disclaimer in the documentation 00019 * and/or other materials provided with the distribution. 00020 * 3. Neither the name of STMicroelectronics nor the names of its contributors 00021 * may be used to endorse or promote products derived from this software 00022 * without specific prior written permission. 00023 * 00024 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00025 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00026 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00027 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 00028 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00029 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00030 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00031 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00032 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00033 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00034 * 00035 ****************************************************************************** 00036 */ 00037 00038 /* Includes ------------------------------------------------------------------*/ 00039 #include "wm8994.h" 00040 00041 /** @addtogroup BSP 00042 * @{ 00043 */ 00044 00045 /** @addtogroup Components 00046 * @{ 00047 */ 00048 00049 /** @addtogroup wm8994 00050 * @brief This file provides a set of functions needed to drive the 00051 * WM8994 audio codec. 00052 * @{ 00053 */ 00054 00055 /** @defgroup WM8994_Private_Types 00056 * @{ 00057 */ 00058 00059 /** 00060 * @} 00061 */ 00062 00063 /** @defgroup WM8994_Private_Defines 00064 * @{ 00065 */ 00066 /* Uncomment this line to enable verifying data sent to codec after each write 00067 operation (for debug purpose) */ 00068 #if !defined (VERIFY_WRITTENDATA) 00069 /* #define VERIFY_WRITTENDATA */ 00070 #endif /* VERIFY_WRITTENDATA */ 00071 /** 00072 * @} 00073 */ 00074 00075 /** @defgroup WM8994_Private_Macros 00076 * @{ 00077 */ 00078 00079 /** 00080 * @} 00081 */ 00082 00083 /** @defgroup WM8994_Private_Variables 00084 * @{ 00085 */ 00086 00087 /* Audio codec driver structure initialization */ 00088 AUDIO_DrvTypeDef wm8994_drv = 00089 { 00090 wm8994_Init, 00091 wm8994_DeInit, 00092 wm8994_ReadID, 00093 00094 wm8994_Play, 00095 wm8994_Pause, 00096 wm8994_Resume, 00097 wm8994_Stop, 00098 00099 wm8994_SetFrequency, 00100 wm8994_SetVolume, 00101 wm8994_SetMute, 00102 wm8994_SetOutputMode, 00103 00104 wm8994_Reset 00105 }; 00106 00107 static uint32_t outputEnabled = 0; 00108 static uint32_t inputEnabled = 0; 00109 /** 00110 * @} 00111 */ 00112 00113 /** @defgroup WM8994_Function_Prototypes 00114 * @{ 00115 */ 00116 static uint8_t CODEC_IO_Write(uint8_t Addr, uint16_t Reg, uint16_t Value); 00117 /** 00118 * @} 00119 */ 00120 00121 /** @defgroup WM8994_Private_Functions 00122 * @{ 00123 */ 00124 00125 /** 00126 * @brief Initializes the audio codec and the control interface. 00127 * @param DeviceAddr: Device address on communication Bus. 00128 * @param OutputInputDevice: can be OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE, 00129 * OUTPUT_DEVICE_BOTH, OUTPUT_DEVICE_AUTO, INPUT_DEVICE_DIGITAL_MICROPHONE_1, 00130 * INPUT_DEVICE_DIGITAL_MICROPHONE_2, INPUT_DEVICE_INPUT_LINE_1 or INPUT_DEVICE_INPUT_LINE_2. 00131 * @param Volume: Initial volume level (from 0 (Mute) to 100 (Max)) 00132 * @param AudioFreq: Audio Frequency 00133 * @retval 0 if correct communication, else wrong communication 00134 */ 00135 uint32_t wm8994_Init(uint16_t DeviceAddr, uint16_t OutputInputDevice, uint8_t Volume, uint32_t AudioFreq) 00136 { 00137 uint32_t counter = 0; 00138 uint16_t output_device = OutputInputDevice & 0xFF; 00139 uint16_t input_device = OutputInputDevice & 0xFF00; 00140 uint16_t power_mgnt_reg_1 = 0; 00141 00142 /* Initialize the Control interface of the Audio Codec */ 00143 AUDIO_IO_Init(); 00144 /* wm8994 Errata Work-Arounds */ 00145 counter += CODEC_IO_Write(DeviceAddr, 0x102, 0x0003); 00146 counter += CODEC_IO_Write(DeviceAddr, 0x817, 0x0000); 00147 counter += CODEC_IO_Write(DeviceAddr, 0x102, 0x0000); 00148 00149 /* Enable VMID soft start (fast), Start-up Bias Current Enabled */ 00150 counter += CODEC_IO_Write(DeviceAddr, 0x39, 0x006C); 00151 00152 /* Enable bias generator, Enable VMID */ 00153 counter += CODEC_IO_Write(DeviceAddr, 0x01, 0x0003); 00154 00155 /* Add Delay */ 00156 AUDIO_IO_Delay(50); 00157 00158 /* Path Configurations for output */ 00159 if (output_device > 0) 00160 { 00161 outputEnabled = 1; 00162 switch (output_device) 00163 { 00164 case OUTPUT_DEVICE_SPEAKER: 00165 /* Enable DAC1 (Left), Enable DAC1 (Right), 00166 Disable DAC2 (Left), Disable DAC2 (Right)*/ 00167 counter += CODEC_IO_Write(DeviceAddr, 0x05, 0x0C0C); 00168 00169 /* Enable the AIF1 Timeslot 0 (Left) to DAC 1 (Left) mixer path */ 00170 counter += CODEC_IO_Write(DeviceAddr, 0x601, 0x0000); 00171 00172 /* Enable the AIF1 Timeslot 0 (Right) to DAC 1 (Right) mixer path */ 00173 counter += CODEC_IO_Write(DeviceAddr, 0x602, 0x0000); 00174 00175 /* Disable the AIF1 Timeslot 1 (Left) to DAC 2 (Left) mixer path */ 00176 counter += CODEC_IO_Write(DeviceAddr, 0x604, 0x0002); 00177 00178 /* Disable the AIF1 Timeslot 1 (Right) to DAC 2 (Right) mixer path */ 00179 counter += CODEC_IO_Write(DeviceAddr, 0x605, 0x0002); 00180 break; 00181 00182 case OUTPUT_DEVICE_HEADPHONE: 00183 /* Disable DAC1 (Left), Disable DAC1 (Right), 00184 Enable DAC2 (Left), Enable DAC2 (Right)*/ 00185 counter += CODEC_IO_Write(DeviceAddr, 0x05, 0x0303); 00186 00187 /* Enable the AIF1 Timeslot 0 (Left) to DAC 1 (Left) mixer path */ 00188 counter += CODEC_IO_Write(DeviceAddr, 0x601, 0x0001); 00189 00190 /* Enable the AIF1 Timeslot 0 (Right) to DAC 1 (Right) mixer path */ 00191 counter += CODEC_IO_Write(DeviceAddr, 0x602, 0x0001); 00192 00193 /* Disable the AIF1 Timeslot 1 (Left) to DAC 2 (Left) mixer path */ 00194 counter += CODEC_IO_Write(DeviceAddr, 0x604, 0x0000); 00195 00196 /* Disable the AIF1 Timeslot 1 (Right) to DAC 2 (Right) mixer path */ 00197 counter += CODEC_IO_Write(DeviceAddr, 0x605, 0x0000); 00198 break; 00199 00200 case OUTPUT_DEVICE_BOTH: 00201 /* Enable DAC1 (Left), Enable DAC1 (Right), 00202 also Enable DAC2 (Left), Enable DAC2 (Right)*/ 00203 counter += CODEC_IO_Write(DeviceAddr, 0x05, 0x0303 | 0x0C0C); 00204 00205 /* Enable the AIF1 Timeslot 0 (Left) to DAC 1 (Left) mixer path */ 00206 counter += CODEC_IO_Write(DeviceAddr, 0x601, 0x0001); 00207 00208 /* Enable the AIF1 Timeslot 0 (Right) to DAC 1 (Right) mixer path */ 00209 counter += CODEC_IO_Write(DeviceAddr, 0x602, 0x0001); 00210 00211 /* Enable the AIF1 Timeslot 1 (Left) to DAC 2 (Left) mixer path */ 00212 counter += CODEC_IO_Write(DeviceAddr, 0x604, 0x0002); 00213 00214 /* Enable the AIF1 Timeslot 1 (Right) to DAC 2 (Right) mixer path */ 00215 counter += CODEC_IO_Write(DeviceAddr, 0x605, 0x0002); 00216 break; 00217 00218 case OUTPUT_DEVICE_AUTO : 00219 default: 00220 /* Disable DAC1 (Left), Disable DAC1 (Right), 00221 Enable DAC2 (Left), Enable DAC2 (Right)*/ 00222 counter += CODEC_IO_Write(DeviceAddr, 0x05, 0x0303); 00223 00224 /* Enable the AIF1 Timeslot 0 (Left) to DAC 1 (Left) mixer path */ 00225 counter += CODEC_IO_Write(DeviceAddr, 0x601, 0x0001); 00226 00227 /* Enable the AIF1 Timeslot 0 (Right) to DAC 1 (Right) mixer path */ 00228 counter += CODEC_IO_Write(DeviceAddr, 0x602, 0x0001); 00229 00230 /* Disable the AIF1 Timeslot 1 (Left) to DAC 2 (Left) mixer path */ 00231 counter += CODEC_IO_Write(DeviceAddr, 0x604, 0x0000); 00232 00233 /* Disable the AIF1 Timeslot 1 (Right) to DAC 2 (Right) mixer path */ 00234 counter += CODEC_IO_Write(DeviceAddr, 0x605, 0x0000); 00235 break; 00236 } 00237 } 00238 else 00239 { 00240 outputEnabled = 0; 00241 } 00242 00243 /* Path Configurations for input */ 00244 if (input_device > 0) 00245 { 00246 inputEnabled = 1; 00247 switch (input_device) 00248 { 00249 case INPUT_DEVICE_DIGITAL_MICROPHONE_2 : 00250 /* Enable AIF1ADC2 (Left), Enable AIF1ADC2 (Right) 00251 * Enable DMICDAT2 (Left), Enable DMICDAT2 (Right) 00252 * Enable Left ADC, Enable Right ADC */ 00253 counter += CODEC_IO_Write(DeviceAddr, 0x04, 0x0C30); 00254 00255 /* Enable AIF1 DRC2 Signal Detect & DRC in AIF1ADC2 Left/Right Timeslot 1 */ 00256 counter += CODEC_IO_Write(DeviceAddr, 0x450, 0x00DB); 00257 00258 /* Disable IN1L, IN1R, IN2L, IN2R, Enable Thermal sensor & shutdown */ 00259 counter += CODEC_IO_Write(DeviceAddr, 0x02, 0x6000); 00260 00261 /* Enable the DMIC2(Left) to AIF1 Timeslot 1 (Left) mixer path */ 00262 counter += CODEC_IO_Write(DeviceAddr, 0x608, 0x0002); 00263 00264 /* Enable the DMIC2(Right) to AIF1 Timeslot 1 (Right) mixer path */ 00265 counter += CODEC_IO_Write(DeviceAddr, 0x609, 0x0002); 00266 00267 /* GPIO1 pin configuration GP1_DIR = output, GP1_FN = AIF1 DRC2 signal detect */ 00268 counter += CODEC_IO_Write(DeviceAddr, 0x700, 0x000E); 00269 break; 00270 00271 case INPUT_DEVICE_INPUT_LINE_1 : 00272 /* Enable AIF1ADC1 (Left), Enable AIF1ADC1 (Right) 00273 * Enable Left ADC, Enable Right ADC */ 00274 counter += CODEC_IO_Write(DeviceAddr, 0x04, 0x0303); 00275 00276 /* Enable AIF1 DRC1 Signal Detect & DRC in AIF1ADC1 Left/Right Timeslot 0 */ 00277 counter += CODEC_IO_Write(DeviceAddr, 0x440, 0x00DB); 00278 00279 /* Enable IN1L and IN1R, Disable IN2L and IN2R, Enable Thermal sensor & shutdown */ 00280 counter += CODEC_IO_Write(DeviceAddr, 0x02, 0x6350); 00281 00282 /* Enable the ADCL(Left) to AIF1 Timeslot 0 (Left) mixer path */ 00283 counter += CODEC_IO_Write(DeviceAddr, 0x606, 0x0002); 00284 00285 /* Enable the ADCR(Right) to AIF1 Timeslot 0 (Right) mixer path */ 00286 counter += CODEC_IO_Write(DeviceAddr, 0x607, 0x0002); 00287 00288 /* GPIO1 pin configuration GP1_DIR = output, GP1_FN = AIF1 DRC1 signal detect */ 00289 counter += CODEC_IO_Write(DeviceAddr, 0x700, 0x000D); 00290 break; 00291 00292 case INPUT_DEVICE_DIGITAL_MICROPHONE_1 : 00293 case INPUT_DEVICE_INPUT_LINE_2 : 00294 default: 00295 /* Actually, no other input devices supported */ 00296 counter++; 00297 break; 00298 } 00299 } 00300 else 00301 { 00302 inputEnabled = 0; 00303 } 00304 00305 /* Clock Configurations */ 00306 switch (AudioFreq) 00307 { 00308 case AUDIO_FREQUENCY_8K: 00309 /* AIF1 Sample Rate = 8 (KHz), ratio=256 */ 00310 counter += CODEC_IO_Write(DeviceAddr, 0x210, 0x0003); 00311 break; 00312 00313 case AUDIO_FREQUENCY_16K: 00314 /* AIF1 Sample Rate = 16 (KHz), ratio=256 */ 00315 counter += CODEC_IO_Write(DeviceAddr, 0x210, 0x0033); 00316 break; 00317 00318 case AUDIO_FREQUENCY_48K: 00319 /* AIF1 Sample Rate = 48 (KHz), ratio=256 */ 00320 counter += CODEC_IO_Write(DeviceAddr, 0x210, 0x0083); 00321 break; 00322 00323 case AUDIO_FREQUENCY_96K: 00324 /* AIF1 Sample Rate = 96 (KHz), ratio=256 */ 00325 counter += CODEC_IO_Write(DeviceAddr, 0x210, 0x00A3); 00326 break; 00327 00328 case AUDIO_FREQUENCY_11K: 00329 /* AIF1 Sample Rate = 11.025 (KHz), ratio=256 */ 00330 counter += CODEC_IO_Write(DeviceAddr, 0x210, 0x0013); 00331 break; 00332 00333 case AUDIO_FREQUENCY_22K: 00334 /* AIF1 Sample Rate = 22.050 (KHz), ratio=256 */ 00335 counter += CODEC_IO_Write(DeviceAddr, 0x210, 0x0043); 00336 break; 00337 00338 case AUDIO_FREQUENCY_44K: 00339 /* AIF1 Sample Rate = 44.1 (KHz), ratio=256 */ 00340 counter += CODEC_IO_Write(DeviceAddr, 0x210, 0x0073); 00341 break; 00342 00343 default: 00344 /* AIF1 Sample Rate = 48 (KHz), ratio=256 */ 00345 counter += CODEC_IO_Write(DeviceAddr, 0x210, 0x0083); 00346 break; 00347 } 00348 /* AIF1 Word Length = 16-bits, AIF1 Format = I2S (Default Register Value) */ 00349 counter += CODEC_IO_Write(DeviceAddr, 0x300, 0x4010); 00350 00351 /* slave mode */ 00352 counter += CODEC_IO_Write(DeviceAddr, 0x302, 0x0000); 00353 00354 /* Enable the DSP processing clock for AIF1, Enable the core clock */ 00355 counter += CODEC_IO_Write(DeviceAddr, 0x208, 0x000A); 00356 00357 /* Enable AIF1 Clock, AIF1 Clock Source = MCLK1 pin */ 00358 counter += CODEC_IO_Write(DeviceAddr, 0x200, 0x0001); 00359 00360 if (output_device > 0) /* Audio output selected */ 00361 { 00362 /* Analog Output Configuration */ 00363 00364 /* Enable SPKRVOL PGA, Enable SPKMIXR, Enable SPKLVOL PGA, Enable SPKMIXL */ 00365 counter += CODEC_IO_Write(DeviceAddr, 0x03, 0x0300); 00366 00367 /* Left Speaker Mixer Volume = 0dB */ 00368 counter += CODEC_IO_Write(DeviceAddr, 0x22, 0x0000); 00369 00370 /* Speaker output mode = Class D, Right Speaker Mixer Volume = 0dB ((0x23, 0x0100) = class AB)*/ 00371 counter += CODEC_IO_Write(DeviceAddr, 0x23, 0x0000); 00372 00373 /* Unmute DAC2 (Left) to Left Speaker Mixer (SPKMIXL) path, 00374 Unmute DAC2 (Right) to Right Speaker Mixer (SPKMIXR) path */ 00375 counter += CODEC_IO_Write(DeviceAddr, 0x36, 0x0300); 00376 00377 /* Enable bias generator, Enable VMID, Enable SPKOUTL, Enable SPKOUTR */ 00378 counter += CODEC_IO_Write(DeviceAddr, 0x01, 0x3003); 00379 00380 /* Headphone/Speaker Enable */ 00381 00382 /* Enable Class W, Class W Envelope Tracking = AIF1 Timeslot 0 */ 00383 counter += CODEC_IO_Write(DeviceAddr, 0x51, 0x0005); 00384 00385 /* Enable bias generator, Enable VMID, Enable HPOUT1 (Left) and Enable HPOUT1 (Right) input stages */ 00386 /* idem for Speaker */ 00387 power_mgnt_reg_1 |= 0x0303 | 0x3003; 00388 counter += CODEC_IO_Write(DeviceAddr, 0x01, power_mgnt_reg_1); 00389 00390 /* Enable HPOUT1 (Left) and HPOUT1 (Right) intermediate stages */ 00391 counter += CODEC_IO_Write(DeviceAddr, 0x60, 0x0022); 00392 00393 /* Enable Charge Pump */ 00394 counter += CODEC_IO_Write(DeviceAddr, 0x4C, 0x9F25); 00395 00396 /* Add Delay */ 00397 AUDIO_IO_Delay(15); 00398 00399 /* Select DAC1 (Left) to Left Headphone Output PGA (HPOUT1LVOL) path */ 00400 counter += CODEC_IO_Write(DeviceAddr, 0x2D, 0x0001); 00401 00402 /* Select DAC1 (Right) to Right Headphone Output PGA (HPOUT1RVOL) path */ 00403 counter += CODEC_IO_Write(DeviceAddr, 0x2E, 0x0001); 00404 00405 /* Enable Left Output Mixer (MIXOUTL), Enable Right Output Mixer (MIXOUTR) */ 00406 /* idem for SPKOUTL and SPKOUTR */ 00407 counter += CODEC_IO_Write(DeviceAddr, 0x03, 0x0030 | 0x0300); 00408 00409 /* Enable DC Servo and trigger start-up mode on left and right channels */ 00410 counter += CODEC_IO_Write(DeviceAddr, 0x54, 0x0033); 00411 00412 /* Add Delay */ 00413 AUDIO_IO_Delay(250); 00414 00415 /* Enable HPOUT1 (Left) and HPOUT1 (Right) intermediate and output stages. Remove clamps */ 00416 counter += CODEC_IO_Write(DeviceAddr, 0x60, 0x00EE); 00417 00418 /* Unmutes */ 00419 00420 /* Unmute DAC 1 (Left) */ 00421 counter += CODEC_IO_Write(DeviceAddr, 0x610, 0x00C0); 00422 00423 /* Unmute DAC 1 (Right) */ 00424 counter += CODEC_IO_Write(DeviceAddr, 0x611, 0x00C0); 00425 00426 /* Unmute the AIF1 Timeslot 0 DAC path */ 00427 counter += CODEC_IO_Write(DeviceAddr, 0x420, 0x0000); 00428 00429 /* Unmute DAC 2 (Left) */ 00430 counter += CODEC_IO_Write(DeviceAddr, 0x612, 0x00C0); 00431 00432 /* Unmute DAC 2 (Right) */ 00433 counter += CODEC_IO_Write(DeviceAddr, 0x613, 0x00C0); 00434 00435 /* Unmute the AIF1 Timeslot 1 DAC2 path */ 00436 counter += CODEC_IO_Write(DeviceAddr, 0x422, 0x0000); 00437 00438 /* Volume Control */ 00439 wm8994_SetVolume(DeviceAddr, Volume); 00440 } 00441 00442 if (input_device > 0) /* Audio input selected */ 00443 { 00444 if ((input_device == INPUT_DEVICE_DIGITAL_MICROPHONE_1) || (input_device == INPUT_DEVICE_DIGITAL_MICROPHONE_2)) 00445 { 00446 /* Enable Microphone bias 1 generator, Enable VMID */ 00447 power_mgnt_reg_1 |= 0x0013; 00448 counter += CODEC_IO_Write(DeviceAddr, 0x01, power_mgnt_reg_1); 00449 00450 /* ADC oversample enable */ 00451 counter += CODEC_IO_Write(DeviceAddr, 0x620, 0x0002); 00452 00453 /* AIF ADC2 HPF enable, HPF cut = voice mode 1 fc=127Hz at fs=8kHz */ 00454 counter += CODEC_IO_Write(DeviceAddr, 0x411, 0x3800); 00455 } 00456 else if ((input_device == INPUT_DEVICE_INPUT_LINE_1) || (input_device == INPUT_DEVICE_INPUT_LINE_2)) 00457 { 00458 /* Enable normal bias generator, Enable VMID */ 00459 power_mgnt_reg_1 |= 0x0003; 00460 counter += CODEC_IO_Write(DeviceAddr, 0x01, power_mgnt_reg_1); 00461 00462 /* Disable mute on IN1L, IN1L Volume = +0dB */ 00463 counter += CODEC_IO_Write(DeviceAddr, 0x18, 0x000B); 00464 00465 /* Disable mute on IN1R, IN1R Volume = +0dB */ 00466 counter += CODEC_IO_Write(DeviceAddr, 0x1A, 0x000B); 00467 00468 /* Disable mute on IN1L_TO_MIXINL, Gain = +0dB */ 00469 counter += CODEC_IO_Write(DeviceAddr, 0x29, 0x0025); 00470 00471 /* Disable mute on IN1R_TO_MIXINL, Gain = +0dB */ 00472 counter += CODEC_IO_Write(DeviceAddr, 0x2A, 0x0025); 00473 00474 /* IN1LN_TO_IN1L, IN1LP_TO_VMID, IN1RN_TO_IN1R, IN1RP_TO_VMID */ 00475 counter += CODEC_IO_Write(DeviceAddr, 0x28, 0x0011); 00476 00477 /* AIF ADC1 HPF enable, HPF cut = hifi mode fc=4Hz at fs=48kHz */ 00478 counter += CODEC_IO_Write(DeviceAddr, 0x410, 0x1800); 00479 } 00480 /* Volume Control */ 00481 wm8994_SetVolume(DeviceAddr, Volume); 00482 } 00483 /* Return communication control value */ 00484 return counter; 00485 } 00486 00487 /** 00488 * @brief Deinitializes the audio codec. 00489 * @param None 00490 * @retval None 00491 */ 00492 void wm8994_DeInit(void) 00493 { 00494 /* Deinitialize Audio Codec interface */ 00495 AUDIO_IO_DeInit(); 00496 } 00497 00498 /** 00499 * @brief Get the WM8994 ID. 00500 * @param DeviceAddr: Device address on communication Bus. 00501 * @retval The WM8994 ID 00502 */ 00503 uint32_t wm8994_ReadID(uint16_t DeviceAddr) 00504 { 00505 /* Initialize the Control interface of the Audio Codec */ 00506 AUDIO_IO_Init(); 00507 00508 return ((uint32_t)AUDIO_IO_Read(DeviceAddr, WM8994_CHIPID_ADDR)); 00509 } 00510 00511 /** 00512 * @brief Start the audio Codec play feature. 00513 * @note For this codec no Play options are required. 00514 * @param DeviceAddr: Device address on communication Bus. 00515 * @retval 0 if correct communication, else wrong communication 00516 */ 00517 uint32_t wm8994_Play(uint16_t DeviceAddr, uint16_t* pBuffer, uint16_t Size) 00518 { 00519 uint32_t counter = 0; 00520 00521 /* Resumes the audio file playing */ 00522 /* Unmute the output first */ 00523 counter += wm8994_SetMute(DeviceAddr, AUDIO_MUTE_OFF); 00524 00525 return counter; 00526 } 00527 00528 /** 00529 * @brief Pauses playing on the audio codec. 00530 * @param DeviceAddr: Device address on communication Bus. 00531 * @retval 0 if correct communication, else wrong communication 00532 */ 00533 uint32_t wm8994_Pause(uint16_t DeviceAddr) 00534 { 00535 uint32_t counter = 0; 00536 00537 /* Pause the audio file playing */ 00538 /* Mute the output first */ 00539 counter += wm8994_SetMute(DeviceAddr, AUDIO_MUTE_ON); 00540 00541 /* Put the Codec in Power save mode */ 00542 counter += CODEC_IO_Write(DeviceAddr, 0x02, 0x01); 00543 00544 return counter; 00545 } 00546 00547 /** 00548 * @brief Resumes playing on the audio codec. 00549 * @param DeviceAddr: Device address on communication Bus. 00550 * @retval 0 if correct communication, else wrong communication 00551 */ 00552 uint32_t wm8994_Resume(uint16_t DeviceAddr) 00553 { 00554 uint32_t counter = 0; 00555 00556 /* Resumes the audio file playing */ 00557 /* Unmute the output first */ 00558 counter += wm8994_SetMute(DeviceAddr, AUDIO_MUTE_OFF); 00559 00560 return counter; 00561 } 00562 00563 /** 00564 * @brief Stops audio Codec playing. It powers down the codec. 00565 * @param DeviceAddr: Device address on communication Bus. 00566 * @param CodecPdwnMode: selects the power down mode. 00567 * - CODEC_PDWN_SW: only mutes the audio codec. When resuming from this 00568 * mode the codec keeps the previous initialization 00569 * (no need to re-Initialize the codec registers). 00570 * - CODEC_PDWN_HW: Physically power down the codec. When resuming from this 00571 * mode, the codec is set to default configuration 00572 * (user should re-Initialize the codec in order to 00573 * play again the audio stream). 00574 * @retval 0 if correct communication, else wrong communication 00575 */ 00576 uint32_t wm8994_Stop(uint16_t DeviceAddr, uint32_t CodecPdwnMode) 00577 { 00578 uint32_t counter = 0; 00579 00580 if (outputEnabled != 0) 00581 { 00582 /* Mute the output first */ 00583 counter += wm8994_SetMute(DeviceAddr, AUDIO_MUTE_ON); 00584 00585 if (CodecPdwnMode == CODEC_PDWN_SW) 00586 { 00587 /* Only output mute required*/ 00588 } 00589 else /* CODEC_PDWN_HW */ 00590 { 00591 /* Mute the AIF1 Timeslot 0 DAC1 path */ 00592 counter += CODEC_IO_Write(DeviceAddr, 0x420, 0x0200); 00593 00594 /* Mute the AIF1 Timeslot 1 DAC2 path */ 00595 counter += CODEC_IO_Write(DeviceAddr, 0x422, 0x0200); 00596 00597 /* Disable DAC1L_TO_HPOUT1L */ 00598 counter += CODEC_IO_Write(DeviceAddr, 0x2D, 0x0000); 00599 00600 /* Disable DAC1R_TO_HPOUT1R */ 00601 counter += CODEC_IO_Write(DeviceAddr, 0x2E, 0x0000); 00602 00603 /* Disable DAC1 and DAC2 */ 00604 counter += CODEC_IO_Write(DeviceAddr, 0x05, 0x0000); 00605 00606 /* Reset Codec by writing in 0x0000 address register */ 00607 counter += CODEC_IO_Write(DeviceAddr, 0x0000, 0x0000); 00608 00609 outputEnabled = 0; 00610 } 00611 } 00612 return counter; 00613 } 00614 00615 /** 00616 * @brief Sets higher or lower the codec volume level. 00617 * @param DeviceAddr: Device address on communication Bus. 00618 * @param Volume: a byte value from 0 to 255 (refer to codec registers 00619 * description for more details). 00620 * @retval 0 if correct communication, else wrong communication 00621 */ 00622 uint32_t wm8994_SetVolume(uint16_t DeviceAddr, uint8_t Volume) 00623 { 00624 uint32_t counter = 0; 00625 uint8_t convertedvol = VOLUME_CONVERT(Volume); 00626 00627 /* Output volume */ 00628 if (outputEnabled != 0) 00629 { 00630 if(convertedvol > 0x3E) 00631 { 00632 /* Unmute audio codec */ 00633 counter += wm8994_SetMute(DeviceAddr, AUDIO_MUTE_OFF); 00634 00635 /* Left Headphone Volume */ 00636 counter += CODEC_IO_Write(DeviceAddr, 0x1C, 0x3F | 0x140); 00637 00638 /* Right Headphone Volume */ 00639 counter += CODEC_IO_Write(DeviceAddr, 0x1D, 0x3F | 0x140); 00640 00641 /* Left Speaker Volume */ 00642 counter += CODEC_IO_Write(DeviceAddr, 0x26, 0x3F | 0x140); 00643 00644 /* Right Speaker Volume */ 00645 counter += CODEC_IO_Write(DeviceAddr, 0x27, 0x3F | 0x140); 00646 } 00647 else if (Volume == 0) 00648 { 00649 /* Mute audio codec */ 00650 counter += wm8994_SetMute(DeviceAddr, AUDIO_MUTE_ON); 00651 } 00652 else 00653 { 00654 /* Unmute audio codec */ 00655 counter += wm8994_SetMute(DeviceAddr, AUDIO_MUTE_OFF); 00656 00657 /* Left Headphone Volume */ 00658 counter += CODEC_IO_Write(DeviceAddr, 0x1C, convertedvol | 0x140); 00659 00660 /* Right Headphone Volume */ 00661 counter += CODEC_IO_Write(DeviceAddr, 0x1D, convertedvol | 0x140); 00662 00663 /* Left Speaker Volume */ 00664 counter += CODEC_IO_Write(DeviceAddr, 0x26, convertedvol | 0x140); 00665 00666 /* Right Speaker Volume */ 00667 counter += CODEC_IO_Write(DeviceAddr, 0x27, convertedvol | 0x140); 00668 } 00669 } 00670 00671 /* Input volume */ 00672 if (inputEnabled != 0) 00673 { 00674 convertedvol = VOLUME_IN_CONVERT(Volume); 00675 00676 /* Left AIF1 ADC1 volume */ 00677 counter += CODEC_IO_Write(DeviceAddr, 0x400, convertedvol | 0x100); 00678 00679 /* Right AIF1 ADC1 volume */ 00680 counter += CODEC_IO_Write(DeviceAddr, 0x401, convertedvol | 0x100); 00681 00682 /* Left AIF1 ADC2 volume */ 00683 counter += CODEC_IO_Write(DeviceAddr, 0x404, convertedvol | 0x100); 00684 00685 /* Right AIF1 ADC2 volume */ 00686 counter += CODEC_IO_Write(DeviceAddr, 0x405, convertedvol | 0x100); 00687 } 00688 return counter; 00689 } 00690 00691 /** 00692 * @brief Enables or disables the mute feature on the audio codec. 00693 * @param DeviceAddr: Device address on communication Bus. 00694 * @param Cmd: AUDIO_MUTE_ON to enable the mute or AUDIO_MUTE_OFF to disable the 00695 * mute mode. 00696 * @retval 0 if correct communication, else wrong communication 00697 */ 00698 uint32_t wm8994_SetMute(uint16_t DeviceAddr, uint32_t Cmd) 00699 { 00700 uint32_t counter = 0; 00701 00702 if (outputEnabled != 0) 00703 { 00704 /* Set the Mute mode */ 00705 if(Cmd == AUDIO_MUTE_ON) 00706 { 00707 /* Soft Mute the AIF1 Timeslot 0 DAC1 path L&R */ 00708 counter += CODEC_IO_Write(DeviceAddr, 0x420, 0x0200); 00709 00710 /* Soft Mute the AIF1 Timeslot 1 DAC2 path L&R */ 00711 counter += CODEC_IO_Write(DeviceAddr, 0x422, 0x0200); 00712 } 00713 else /* AUDIO_MUTE_OFF Disable the Mute */ 00714 { 00715 /* Unmute the AIF1 Timeslot 0 DAC1 path L&R */ 00716 counter += CODEC_IO_Write(DeviceAddr, 0x420, 0x0000); 00717 00718 /* Unmute the AIF1 Timeslot 1 DAC2 path L&R */ 00719 counter += CODEC_IO_Write(DeviceAddr, 0x422, 0x0000); 00720 } 00721 } 00722 return counter; 00723 } 00724 00725 /** 00726 * @brief Switch dynamically (while audio file is played) the output target 00727 * (speaker or headphone). 00728 * @param DeviceAddr: Device address on communication Bus. 00729 * @param Output: specifies the audio output target: OUTPUT_DEVICE_SPEAKER, 00730 * OUTPUT_DEVICE_HEADPHONE, OUTPUT_DEVICE_BOTH or OUTPUT_DEVICE_AUTO 00731 * @retval 0 if correct communication, else wrong communication 00732 */ 00733 uint32_t wm8994_SetOutputMode(uint16_t DeviceAddr, uint8_t Output) 00734 { 00735 uint32_t counter = 0; 00736 00737 switch (Output) 00738 { 00739 case OUTPUT_DEVICE_SPEAKER: 00740 /* Enable DAC1 (Left), Enable DAC1 (Right), 00741 Disable DAC2 (Left), Disable DAC2 (Right)*/ 00742 counter += CODEC_IO_Write(DeviceAddr, 0x05, 0x0C0C); 00743 00744 /* Enable the AIF1 Timeslot 0 (Left) to DAC 1 (Left) mixer path */ 00745 counter += CODEC_IO_Write(DeviceAddr, 0x601, 0x0000); 00746 00747 /* Enable the AIF1 Timeslot 0 (Right) to DAC 1 (Right) mixer path */ 00748 counter += CODEC_IO_Write(DeviceAddr, 0x602, 0x0000); 00749 00750 /* Disable the AIF1 Timeslot 1 (Left) to DAC 2 (Left) mixer path */ 00751 counter += CODEC_IO_Write(DeviceAddr, 0x604, 0x0002); 00752 00753 /* Disable the AIF1 Timeslot 1 (Right) to DAC 2 (Right) mixer path */ 00754 counter += CODEC_IO_Write(DeviceAddr, 0x605, 0x0002); 00755 break; 00756 00757 case OUTPUT_DEVICE_HEADPHONE: 00758 /* Disable DAC1 (Left), Disable DAC1 (Right), 00759 Enable DAC2 (Left), Enable DAC2 (Right)*/ 00760 counter += CODEC_IO_Write(DeviceAddr, 0x05, 0x0303); 00761 00762 /* Enable the AIF1 Timeslot 0 (Left) to DAC 1 (Left) mixer path */ 00763 counter += CODEC_IO_Write(DeviceAddr, 0x601, 0x0001); 00764 00765 /* Enable the AIF1 Timeslot 0 (Right) to DAC 1 (Right) mixer path */ 00766 counter += CODEC_IO_Write(DeviceAddr, 0x602, 0x0001); 00767 00768 /* Disable the AIF1 Timeslot 1 (Left) to DAC 2 (Left) mixer path */ 00769 counter += CODEC_IO_Write(DeviceAddr, 0x604, 0x0000); 00770 00771 /* Disable the AIF1 Timeslot 1 (Right) to DAC 2 (Right) mixer path */ 00772 counter += CODEC_IO_Write(DeviceAddr, 0x605, 0x0000); 00773 break; 00774 00775 case OUTPUT_DEVICE_BOTH: 00776 /* Enable DAC1 (Left), Enable DAC1 (Right), 00777 also Enable DAC2 (Left), Enable DAC2 (Right)*/ 00778 counter += CODEC_IO_Write(DeviceAddr, 0x05, 0x0303 | 0x0C0C); 00779 00780 /* Enable the AIF1 Timeslot 0 (Left) to DAC 1 (Left) mixer path */ 00781 counter += CODEC_IO_Write(DeviceAddr, 0x601, 0x0001); 00782 00783 /* Enable the AIF1 Timeslot 0 (Right) to DAC 1 (Right) mixer path */ 00784 counter += CODEC_IO_Write(DeviceAddr, 0x602, 0x0001); 00785 00786 /* Enable the AIF1 Timeslot 1 (Left) to DAC 2 (Left) mixer path */ 00787 counter += CODEC_IO_Write(DeviceAddr, 0x604, 0x0002); 00788 00789 /* Enable the AIF1 Timeslot 1 (Right) to DAC 2 (Right) mixer path */ 00790 counter += CODEC_IO_Write(DeviceAddr, 0x605, 0x0002); 00791 break; 00792 00793 default: 00794 /* Disable DAC1 (Left), Disable DAC1 (Right), 00795 Enable DAC2 (Left), Enable DAC2 (Right)*/ 00796 counter += CODEC_IO_Write(DeviceAddr, 0x05, 0x0303); 00797 00798 /* Enable the AIF1 Timeslot 0 (Left) to DAC 1 (Left) mixer path */ 00799 counter += CODEC_IO_Write(DeviceAddr, 0x601, 0x0001); 00800 00801 /* Enable the AIF1 Timeslot 0 (Right) to DAC 1 (Right) mixer path */ 00802 counter += CODEC_IO_Write(DeviceAddr, 0x602, 0x0001); 00803 00804 /* Disable the AIF1 Timeslot 1 (Left) to DAC 2 (Left) mixer path */ 00805 counter += CODEC_IO_Write(DeviceAddr, 0x604, 0x0000); 00806 00807 /* Disable the AIF1 Timeslot 1 (Right) to DAC 2 (Right) mixer path */ 00808 counter += CODEC_IO_Write(DeviceAddr, 0x605, 0x0000); 00809 break; 00810 } 00811 return counter; 00812 } 00813 00814 /** 00815 * @brief Sets new frequency. 00816 * @param DeviceAddr: Device address on communication Bus. 00817 * @param AudioFreq: Audio frequency used to play the audio stream. 00818 * @retval 0 if correct communication, else wrong communication 00819 */ 00820 uint32_t wm8994_SetFrequency(uint16_t DeviceAddr, uint32_t AudioFreq) 00821 { 00822 uint32_t counter = 0; 00823 00824 /* Clock Configurations */ 00825 switch (AudioFreq) 00826 { 00827 case AUDIO_FREQUENCY_8K: 00828 /* AIF1 Sample Rate = 8 (KHz), ratio=256 */ 00829 counter += CODEC_IO_Write(DeviceAddr, 0x210, 0x0003); 00830 break; 00831 00832 case AUDIO_FREQUENCY_16K: 00833 /* AIF1 Sample Rate = 16 (KHz), ratio=256 */ 00834 counter += CODEC_IO_Write(DeviceAddr, 0x210, 0x0033); 00835 break; 00836 00837 case AUDIO_FREQUENCY_48K: 00838 /* AIF1 Sample Rate = 48 (KHz), ratio=256 */ 00839 counter += CODEC_IO_Write(DeviceAddr, 0x210, 0x0083); 00840 break; 00841 00842 case AUDIO_FREQUENCY_96K: 00843 /* AIF1 Sample Rate = 96 (KHz), ratio=256 */ 00844 counter += CODEC_IO_Write(DeviceAddr, 0x210, 0x00A3); 00845 break; 00846 00847 case AUDIO_FREQUENCY_11K: 00848 /* AIF1 Sample Rate = 11.025 (KHz), ratio=256 */ 00849 counter += CODEC_IO_Write(DeviceAddr, 0x210, 0x0013); 00850 break; 00851 00852 case AUDIO_FREQUENCY_22K: 00853 /* AIF1 Sample Rate = 22.050 (KHz), ratio=256 */ 00854 counter += CODEC_IO_Write(DeviceAddr, 0x210, 0x0043); 00855 break; 00856 00857 case AUDIO_FREQUENCY_44K: 00858 /* AIF1 Sample Rate = 44.1 (KHz), ratio=256 */ 00859 counter += CODEC_IO_Write(DeviceAddr, 0x210, 0x0073); 00860 break; 00861 00862 default: 00863 /* AIF1 Sample Rate = 48 (KHz), ratio=256 */ 00864 counter += CODEC_IO_Write(DeviceAddr, 0x210, 0x0083); 00865 break; 00866 } 00867 return counter; 00868 } 00869 00870 /** 00871 * @brief Resets wm8994 registers. 00872 * @param DeviceAddr: Device address on communication Bus. 00873 * @retval 0 if correct communication, else wrong communication 00874 */ 00875 uint32_t wm8994_Reset(uint16_t DeviceAddr) 00876 { 00877 uint32_t counter = 0; 00878 00879 /* Reset Codec by writing in 0x0000 address register */ 00880 counter = CODEC_IO_Write(DeviceAddr, 0x0000, 0x0000); 00881 outputEnabled = 0; 00882 inputEnabled=0; 00883 00884 return counter; 00885 } 00886 00887 /** 00888 * @brief Writes/Read a single data. 00889 * @param Addr: I2C address 00890 * @param Reg: Reg address 00891 * @param Value: Data to be written 00892 * @retval None 00893 */ 00894 static uint8_t CODEC_IO_Write(uint8_t Addr, uint16_t Reg, uint16_t Value) 00895 { 00896 uint32_t result = 0; 00897 00898 AUDIO_IO_Write(Addr, Reg, Value); 00899 00900 #ifdef VERIFY_WRITTENDATA 00901 /* Verify that the data has been correctly written */ 00902 result = (AUDIO_IO_Read(Addr, Reg) == Value)? 0:1; 00903 #endif /* VERIFY_WRITTENDATA */ 00904 00905 return result; 00906 } 00907 00908 /** 00909 * @} 00910 */ 00911 00912 /** 00913 * @} 00914 */ 00915 00916 /** 00917 * @} 00918 */ 00919 00920 /** 00921 * @} 00922 */ 00923 00924 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Tue Jul 12 2022 15:39:22 by
