bugfixes and reduced version for disco board only
Dependents: Scope DISCO-F746NG_Sinewave DISCO-F746NG_Sweep DISCO-F746NG_Oscilloscope ... more
Fork of BSP_DISCO_F746NG_patch by
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 17:59:55 by 1.7.2