123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621 |
- /*
- * Copyright (c) 2016, Freescale Semiconductor, Inc.
- * Copyright 2016-2017 NXP
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * o Redistributions of source code must retain the above copyright notice, this list
- * of conditions and the following disclaimer.
- *
- * o Redistributions in binary form must reproduce the above copyright notice, this
- * list of conditions and the following disclaimer in the documentation and/or
- * other materials provided with the distribution.
- *
- * o Neither the name of the copyright holder nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #include "fsl_wm8960.h"
- #include "fsl_common.h"
- /*******************************************************************************
- * Definitations
- ******************************************************************************/
- /*******************************************************************************
- * Prototypes
- ******************************************************************************/
- /*******************************************************************************
- * Variables
- ******************************************************************************/
- /*
- * wm8960 register cache
- * We can't read the WM8960 register space when we are
- * using 2 wire for device control, so we cache them instead.
- */
- static const uint16_t wm8960_reg[WM8960_CACHEREGNUM] = {
- 0x0097, 0x0097, 0x0000, 0x0000, 0x0000, 0x0008, 0x0000, 0x000a, 0x01c0, 0x0000, 0x00ff, 0x00ff, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x007b, 0x0100, 0x0032, 0x0000, 0x00c3, 0x00c3, 0x01c0, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0100, 0x0100, 0x0050, 0x0050, 0x0050, 0x0050, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0040, 0x0000, 0x0000, 0x0050, 0x0050, 0x0000, 0x0002, 0x0037, 0x004d, 0x0080, 0x0008, 0x0031, 0x0026, 0x00e9,
- };
- static uint16_t reg_cache[WM8960_CACHEREGNUM];
- /*******************************************************************************
- * Code
- ******************************************************************************/
- void WM8960_Init(wm8960_handle_t *handle, wm8960_config_t *config)
- {
- uint32_t i = 4000000;
- memcpy(reg_cache, wm8960_reg, sizeof(wm8960_reg));
- /* Set WM8960 I2C address */
- handle->xfer.slaveAddress = WM8960_I2C_ADDR;
- /* NULL pointer means default setting. */
- if (config == NULL)
- {
- /*
- * Reset all registers
- */
- WM8960_WriteReg(handle, WM8960_RESET, 0x00);
- WM8960_WriteReg(handle, WM8960_IFACE2, 0x40);
- /*
- * VMID=50K, Enable VREF, AINL, AINR, ADCL and ADCR
- * I2S_IN (bit 0), I2S_OUT (bit 1), DAP (bit 4), DAC (bit 5), ADC (bit 6) are powered on
- */
- WM8960_WriteReg(handle, WM8960_POWER1, 0xCA);
- /*
- * Enable DACL, DACR, LOUT1, ROUT1, PLL down
- */
- WM8960_WriteReg(handle, WM8960_POWER2, 0x1E0);
- /*
- * Enable left and right channel input PGA, left and right output mixer
- */
- WM8960_WriteReg(handle, WM8960_POWER3, 0xC);
- /* Configure SYS_FS clock to 44.1kHz, MCLK_FREQ to 256*Fs, SYSCLK derived from MCLK input */
- WM8960_WriteReg(handle, WM8960_CLOCK1, 0x00);
- /*
- * Audio data length = 32bit, Left justified data format
- */
- WM8960_WriteReg(handle, WM8960_IFACE1, 0x0D);
- /*
- * LMICBOOST = 0dB, Connect left and right PGA to left and right Input Boost Mixer
- */
- WM8960_WriteReg(handle, WM8960_LINPATH, 0x18);
- WM8960_WriteReg(handle, WM8960_RINPATH, 0x18);
- /*
- * Left and right input boost, LIN3BOOST and RIN3BOOST = 0dB
- */
- WM8960_WriteReg(handle, WM8960_INBMIX1, 0x70);
- WM8960_WriteReg(handle, WM8960_INBMIX2, 0x70);
- /*
- * Left DAC and LINPUT3 to left output mixer, LINPUT3 left output mixer volume = 0dB
- */
- WM8960_WriteReg(handle, WM8960_LOUTMIX, 0x100);
- /*
- * Right DAC and RINPUT3 to right output mixer, RINPUT3 right output mixer volume = 0dB
- */
- WM8960_WriteReg(handle, WM8960_ROUTMIX, 0x100);
- WM8960_WriteReg(handle, WM8960_BYPASS1, 0x0);
- WM8960_WriteReg(handle, WM8960_BYPASS2, 0x0);
- WM8960_WriteReg(handle, WM8960_MONOMIX1, 0x00);
- WM8960_WriteReg(handle, WM8960_MONOMIX2, 0x00);
- }
- else
- {
- WM8960_SetDataRoute(handle, config->route);
- WM8960_SetProtocol(handle, config->bus);
- WM8960_SetMasterSlave(handle, config->master_slave);
- }
- WM8960_WriteReg(handle, WM8960_ADDCTL1, 0x0C4);
- WM8960_WriteReg(handle, WM8960_ADDCTL4, 0x40);
- /*
- * ADC volume, 0dB
- */
- WM8960_WriteReg(handle, WM8960_LADC, 0x1F3);
- WM8960_WriteReg(handle, WM8960_RADC, 0x1F3);
- /*
- * Digital DAC volume, 0dB
- */
- WM8960_WriteReg(handle, WM8960_LDAC, 0x1E0);
- WM8960_WriteReg(handle, WM8960_RDAC, 0x1E0);
- /*
- * Headphone volume, LOUT1 and ROUT1, 0dB
- */
- WM8960_WriteReg(handle, WM8960_LOUT1, 0x16F);
- WM8960_WriteReg(handle, WM8960_ROUT1, 0x16F);
- /* Delay for some while */
- while (i)
- {
- __ASM("nop");
- i--;
- }
- /* Unmute DAC. */
- WM8960_WriteReg(handle, WM8960_DACCTL1, 0x0000);
- }
- void WM8960_Deinit(wm8960_handle_t *handle)
- {
- WM8960_SetModule(handle, kWM8960_ModuleADC, false);
- WM8960_SetModule(handle, kWM8960_ModuleDAC, false);
- WM8960_SetModule(handle, kWM8960_ModuleVREF, false);
- WM8960_SetModule(handle, kWM8960_ModuleLineIn, false);
- WM8960_SetModule(handle, kWM8960_ModuleLineOut, false);
- WM8960_SetModule(handle, kWM8960_ModuleSpeaker, false);
- }
- void WM8960_SetMasterSlave(wm8960_handle_t *handle, bool master)
- {
- if (master == 1)
- {
- WM8960_ModifyReg(handle, WM8960_IFACE1, WM8960_IFACE1_MS_MASK, WM8960_IFACE1_MS(WM8960_IFACE1_MASTER));
- }
- else
- {
- WM8960_ModifyReg(handle, WM8960_IFACE1, WM8960_IFACE1_MS_MASK, WM8960_IFACE1_MS(WM8960_IFACE1_SLAVE));
- }
- }
- status_t WM8960_SetModule(wm8960_handle_t *handle, wm8960_module_t module, bool isEnabled)
- {
- status_t ret = kStatus_Success;
- switch (module)
- {
- case kWM8960_ModuleADC:
- WM8960_ModifyReg(handle, WM8960_POWER1, WM8960_POWER1_ADCL_MASK,
- ((uint16_t)isEnabled << WM8960_POWER1_ADCL_SHIFT));
- WM8960_ModifyReg(handle, WM8960_POWER1, WM8960_POWER1_ADCR_MASK,
- ((uint16_t)isEnabled << WM8960_POWER1_ADCR_SHIFT));
- break;
- case kWM8960_ModuleDAC:
- WM8960_ModifyReg(handle, WM8960_POWER2, WM8960_POWER2_DACL_MASK,
- ((uint16_t)isEnabled << WM8960_POWER2_DACL_SHIFT));
- WM8960_ModifyReg(handle, WM8960_POWER2, WM8960_POWER2_DACR_MASK,
- ((uint16_t)isEnabled << WM8960_POWER2_DACR_SHIFT));
- break;
- case kWM8960_ModuleVREF:
- WM8960_ModifyReg(handle, WM8960_POWER1, WM8960_POWER1_VREF_MASK,
- ((uint16_t)isEnabled << WM8960_POWER1_VREF_SHIFT));
- break;
- case kWM8960_ModuleLineIn:
- WM8960_ModifyReg(handle, WM8960_POWER1, WM8960_POWER1_AINL_MASK,
- ((uint16_t)isEnabled << WM8960_POWER1_AINL_SHIFT));
- WM8960_ModifyReg(handle, WM8960_POWER1, WM8960_POWER1_AINR_MASK,
- ((uint16_t)isEnabled << WM8960_POWER1_AINR_SHIFT));
- break;
- case kWM8960_ModuleLineOut:
- WM8960_ModifyReg(handle, WM8960_POWER2, WM8960_POWER2_LOUT1_MASK,
- ((uint16_t)isEnabled << WM8960_POWER2_LOUT1_SHIFT));
- WM8960_ModifyReg(handle, WM8960_POWER2, WM8960_POWER2_ROUT1_MASK,
- ((uint16_t)isEnabled << WM8960_POWER2_ROUT1_SHIFT));
- break;
- case kWM8960_ModuleSpeaker:
- WM8960_ModifyReg(handle, WM8960_POWER2, WM8960_POWER2_SPKL_MASK,
- ((uint16_t)isEnabled << WM8960_POWER2_SPKL_SHIFT));
- WM8960_ModifyReg(handle, WM8960_POWER2, WM8960_POWER2_SPKR_MASK,
- ((uint16_t)isEnabled << WM8960_POWER2_SPKR_SHIFT));
- WM8960_WriteReg(handle, WM8960_CLASSD1, 0xF7);
- break;
- default:
- ret = kStatus_InvalidArgument;
- break;
- }
- return ret;
- }
- status_t WM8960_SetDataRoute(wm8960_handle_t *handle, wm8960_route_t route)
- {
- status_t ret = kStatus_Success;
- switch (route)
- {
- case kWM8960_RouteBypass:
- /* Bypass means from line-in to HP*/
- /*
- * Left LINPUT3 to left output mixer, LINPUT3 left output mixer volume = 0dB
- */
- WM8960_WriteReg(handle, WM8960_LOUTMIX, 0x80);
- /*
- * Right RINPUT3 to right output mixer, RINPUT3 right output mixer volume = 0dB
- */
- WM8960_WriteReg(handle, WM8960_ROUTMIX, 0x80);
- break;
- case kWM8960_RoutePlayback:
- /* Data route I2S_IN-> DAC-> HP */
- /*
- * Left DAC to left output mixer, LINPUT3 left output mixer volume = 0dB
- */
- WM8960_WriteReg(handle, WM8960_LOUTMIX, 0x100);
- /*
- * Right DAC to right output mixer, RINPUT3 right output mixer volume = 0dB
- */
- WM8960_WriteReg(handle, WM8960_ROUTMIX, 0x100);
- break;
- case kWM8960_RoutePlaybackandRecord:
- /* I2S IN->DAC->HP LINE_IN->ADC->I2S_OUT */
- /*
- * Left and right input boost, LIN3BOOST and RIN3BOOST = 0dB
- */
- WM8960_WriteReg(handle, WM8960_INBMIX1, 0x50);
- WM8960_WriteReg(handle, WM8960_INBMIX2, 0x50);
- /*
- * Left DAC to left output mixer, LINPUT3 left output mixer volume = 0dB
- */
- WM8960_WriteReg(handle, WM8960_LOUTMIX, 0x100);
- /*
- * Right DAC to right output mixer, RINPUT3 right output mixer volume = 0dB
- */
- WM8960_WriteReg(handle, WM8960_ROUTMIX, 0x100);
- break;
- case kWM8960_RoutePlaybackwithDAP:
- /* I2S_IN->DAP->DAC->HP */
- break;
- case kWM8960_RoutePlaybackwithDAPandRecord:
- /* I2S_IN->DAP->DAC->HP, LINE_IN->ADC->I2S_OUT */
- break;
- case kWM8960_RouteRecord:
- /* LINE_IN->ADC->I2S_OUT */
- /*
- * Left and right input boost, LIN3BOOST and RIN3BOOST = 0dB
- */
- WM8960_WriteReg(handle, WM8960_INBMIX1, 0x50);
- WM8960_WriteReg(handle, WM8960_INBMIX2, 0x50);
- break;
- default:
- ret = kStatus_InvalidArgument;
- break;
- }
- return ret;
- }
- status_t WM8960_SetProtocol(wm8960_handle_t *handle, wm8960_protocol_t protocol)
- {
- status_t ret = kStatus_Success;
- switch (protocol)
- {
- case kWM8960_BusI2S:
- WM8960_ModifyReg(handle, WM8960_IFACE1, WM8960_IFACE1_FORMAT_MASK,
- WM8960_IFACE1_FORMAT(WM8960_IFACE1_FORMAT_I2S));
- break;
- case kWM8960_BusLeftJustified:
- WM8960_ModifyReg(handle, WM8960_IFACE1, WM8960_IFACE1_FORMAT_MASK,
- WM8960_IFACE1_FORMAT(WM8960_IFACE1_FORMAT_LJ));
- break;
- case kWM8960_BusRightJustified:
- WM8960_ModifyReg(handle, WM8960_IFACE1, WM8960_IFACE1_FORMAT_MASK,
- WM8960_IFACE1_FORMAT(WM8960_IFACE1_FORMAT_RJ));
- break;
- case kWM8960_BusPCMA:
- WM8960_ModifyReg(handle, WM8960_IFACE1, WM8960_IFACE1_FORMAT_MASK,
- WM8960_IFACE1_FORMAT(WM8960_IFACE1_FORMAT_DSP));
- WM8960_ModifyReg(handle, WM8960_IFACE1, WM8960_IFACE1_LRP_MASK, WM8960_IFACE1_LRP(WM8960_IFACE1_DSP_MODEA));
- break;
- case kWM8960_BusPCMB:
- WM8960_ModifyReg(handle, WM8960_IFACE1, WM8960_IFACE1_FORMAT_MASK,
- WM8960_IFACE1_FORMAT(WM8960_IFACE1_FORMAT_DSP));
- WM8960_ModifyReg(handle, WM8960_IFACE1, WM8960_IFACE1_LRP_MASK, WM8960_IFACE1_LRP(WM8960_IFACE1_DSP_MODEB));
- break;
- default:
- ret = kStatus_InvalidArgument;
- break;
- }
- WM8960_ModifyReg(handle, WM8960_IFACE1, WM8960_IFACE1_WL_MASK, WM8960_IFACE1_WL(WM8960_IFACE1_WL_32BITS));
- return ret;
- }
- status_t WM8960_SetVolume(wm8960_handle_t *handle, wm8960_module_t module, uint32_t volume)
- {
- uint16_t vol = 0;
- status_t ret = kStatus_Success;
- switch (module)
- {
- case kWM8960_ModuleADC:
- vol = 0x100 | volume;
- ret = WM8960_WriteReg(handle, WM8960_LADC, vol);
- ret = WM8960_WriteReg(handle, WM8960_RADC, vol);
- break;
- case kWM8960_ModuleDAC:
- vol = 0x100 | volume;
- ret = WM8960_WriteReg(handle, WM8960_LDAC, vol);
- ret = WM8960_WriteReg(handle, WM8960_RDAC, vol);
- break;
- case kWM8960_ModuleHP:
- vol = 0x100 | volume;
- ret = WM8960_WriteReg(handle, WM8960_LOUT1, vol);
- ret = WM8960_WriteReg(handle, WM8960_ROUT1, vol);
- break;
- case kWM8960_ModuleLineIn:
- vol = 0x100 | volume;
- ret = WM8960_WriteReg(handle, WM8960_LINVOL, vol);
- ret = WM8960_WriteReg(handle, WM8960_RINVOL, vol);
- break;
- case kWM8960_ModuleSpeaker:
- vol = 0x100 | volume;
- ret = WM8960_WriteReg(handle, WM8960_LOUT2, vol);
- ret = WM8960_WriteReg(handle, WM8960_ROUT2, vol);
- break;
- default:
- ret = kStatus_InvalidArgument;
- break;
- }
- return ret;
- }
- uint32_t WM8960_GetVolume(wm8960_handle_t *handle, wm8960_module_t module)
- {
- uint16_t vol = 0;
- switch (module)
- {
- case kWM8960_ModuleADC:
- WM8960_ReadReg(WM8960_LADC, &vol);
- vol &= 0xFF;
- break;
- case kWM8960_ModuleDAC:
- WM8960_ReadReg(WM8960_LDAC, &vol);
- vol &= 0xFF;
- break;
- case kWM8960_ModuleHP:
- WM8960_ReadReg(WM8960_LOUT1, &vol);
- vol &= 0x7F;
- break;
- case kWM8960_ModuleLineOut:
- WM8960_ReadReg(WM8960_LINVOL, &vol);
- vol &= 0x3F;
- break;
- default:
- vol = 0;
- break;
- }
- return vol;
- }
- status_t WM8960_SetMute(wm8960_handle_t *handle, wm8960_module_t module, bool isEnabled)
- {
- status_t ret = kStatus_Success;
- switch (module)
- {
- case kWM8960_ModuleADC:
- /*
- * Digital Mute
- */
- if (isEnabled)
- {
- ret = WM8960_WriteReg(handle, WM8960_LADC, 0x100);
- ret = WM8960_WriteReg(handle, WM8960_RADC, 0x100);
- }
- else
- {
- ret = WM8960_WriteReg(handle, WM8960_LADC, 0x1C3);
- ret = WM8960_WriteReg(handle, WM8960_RADC, 0x1C3);
- }
- break;
- case kWM8960_ModuleDAC:
- /*
- * Digital mute
- */
- if (isEnabled)
- {
- ret = WM8960_WriteReg(handle, WM8960_LDAC, 0x100);
- ret = WM8960_WriteReg(handle, WM8960_RDAC, 0x100);
- }
- else
- {
- ret = WM8960_WriteReg(handle, WM8960_LDAC, 0x1FF);
- ret = WM8960_WriteReg(handle, WM8960_RDAC, 0x1FF);
- }
- break;
- case kWM8960_ModuleHP:
- /*
- * Analog mute
- */
- if (isEnabled)
- {
- ret = WM8960_WriteReg(handle, WM8960_LOUT1, 0x100);
- ret = WM8960_WriteReg(handle, WM8960_ROUT1, 0x100);
- }
- else
- {
- ret = WM8960_WriteReg(handle, WM8960_LOUT1, 0x179);
- ret = WM8960_WriteReg(handle, WM8960_ROUT1, 0x179);
- }
- break;
- case kWM8960_ModuleLineOut:
- break;
- default:
- ret = kStatus_InvalidArgument;
- break;
- }
- return ret;
- }
- status_t WM8960_ConfigDataFormat(wm8960_handle_t *handle, uint32_t mclk, uint32_t sample_rate, uint8_t bits)
- {
- status_t retval = kStatus_Success;
- switch (sample_rate)
- {
- case 8000:
- retval = WM8960_WriteReg(handle, WM8960_CLOCK1, 0x1B0);
- break;
- case 11025:
- retval = WM8960_WriteReg(handle, WM8960_CLOCK1, 0xD8);
- break;
- case 12000:
- retval = WM8960_WriteReg(handle, WM8960_CLOCK1, 0x120);
- break;
- case 16000:
- retval = WM8960_WriteReg(handle, WM8960_CLOCK1, 0xD8);
- break;
- case 22050:
- retval = WM8960_WriteReg(handle, WM8960_CLOCK1, 0xD8);
- break;
- case 24000:
- retval = WM8960_WriteReg(handle, WM8960_CLOCK1, 0x90);
- break;
- case 32000:
- retval = WM8960_WriteReg(handle, WM8960_CLOCK1, 0x48);
- break;
- case 44100:
- retval = WM8960_WriteReg(handle, WM8960_CLOCK1, 0xD8);
- break;
- case 48000:
- retval = WM8960_WriteReg(handle, WM8960_CLOCK1, 0x00);
- break;
- default:
- retval = kStatus_InvalidArgument;
- break;
- }
- /*
- * Slave mode (MS = 0), LRP = 0, 32bit WL, left justified (FORMAT[1:0]=0b01)
- */
- switch (bits)
- {
- case 16:
- retval = WM8960_ModifyReg(handle, WM8960_IFACE1, WM8960_IFACE1_WL_MASK,
- WM8960_IFACE1_WL(WM8960_IFACE1_WL_16BITS));
- break;
- case 20:
- retval = WM8960_ModifyReg(handle, WM8960_IFACE1, WM8960_IFACE1_WL_MASK,
- WM8960_IFACE1_WL(WM8960_IFACE1_WL_20BITS));
- break;
- case 24:
- retval = WM8960_ModifyReg(handle, WM8960_IFACE1, WM8960_IFACE1_WL_MASK,
- WM8960_IFACE1_WL(WM8960_IFACE1_WL_24BITS));
- break;
- case 32:
- retval = WM8960_ModifyReg(handle, WM8960_IFACE1, WM8960_IFACE1_WL_MASK,
- WM8960_IFACE1_WL(WM8960_IFACE1_WL_32BITS));
- break;
- default:
- retval = kStatus_InvalidArgument;
- break;
- }
- return retval;
- }
- status_t WM8960_SetJackDetect(wm8960_handle_t *handle, bool isEnabled)
- {
- uint8_t retval = 0;
- uint16_t val = 0;
- WM8960_ReadReg(WM8960_ADDCTL2, &val);
- if (isEnabled)
- {
- val |= 0x40U;
- }
- else
- {
- val &= 0xCF;
- }
- retval = WM8960_WriteReg(handle, WM8960_ADDCTL2, val);
- return retval;
- }
- status_t WM8960_WriteReg(wm8960_handle_t *handle, uint8_t reg, uint16_t val)
- {
- uint8_t cmd, buff;
- uint8_t retval = 0;
- /* The register address */
- cmd = (reg << 1) | ((val >> 8U) & 0x0001U);
- /* Data */
- buff = val & 0xFF;
- /* Copy data to cache */
- reg_cache[reg] = val;
- #if defined(FSL_FEATURE_SOC_LPI2C_COUNT) && (FSL_FEATURE_SOC_LPI2C_COUNT)
- uint8_t data[2];
- data[0] = cmd;
- data[1] = buff;
- retval = LPI2C_MasterStart(handle->base, WM8960_I2C_ADDR, kLPI2C_Write);
- retval = LPI2C_MasterSend(handle->base, data, 2);
- retval = LPI2C_MasterStop(handle->base);
- #else
- /* Config the I2C xfer */
- handle->xfer.direction = kI2C_Write;
- handle->xfer.subaddress = cmd;
- handle->xfer.subaddressSize = 1U;
- handle->xfer.data = &buff;
- handle->xfer.dataSize = 1U;
- retval = I2C_MasterTransferBlocking(handle->base, &handle->xfer);
- #endif
- if (retval != kStatus_Success)
- {
- return kStatus_Fail;
- }
- return kStatus_Success;
- }
- status_t WM8960_ReadReg(uint8_t reg, uint16_t *val)
- {
- if (reg >= WM8960_CACHEREGNUM)
- {
- return kStatus_InvalidArgument;
- }
- *val = reg_cache[reg];
- return kStatus_Success;
- }
- status_t WM8960_ModifyReg(wm8960_handle_t *handle, uint8_t reg, uint16_t mask, uint16_t val)
- {
- uint8_t retval = 0;
- uint16_t reg_val = 0;
- retval = WM8960_ReadReg(reg, ®_val);
- if (retval != kStatus_Success)
- {
- return kStatus_Fail;
- }
- reg_val &= (uint16_t)~mask;
- reg_val |= val;
- retval = WM8960_WriteReg(handle, reg, reg_val);
- if (retval != kStatus_Success)
- {
- return kStatus_Fail;
- }
- return kStatus_Success;
- }
|