1 /*
2  * Copyright  2021 NXP
3  * All rights reserved.
4  *
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_codec_wm8904_adapter.h"
10 #include "fsl_codec_common.h"
11 /*******************************************************************************
12  * Definitions
13  ******************************************************************************/
14 /*! @brief module capability definition */
15 #define HAL_WM8904_MODULE_CAPABILITY                                                                              \
16     kCODEC_SupportModuleADC | kCODEC_SupportModuleDAC | kCODEC_SupportModulePGA | kCODEC_SupportModuleHeadphone | \
17         kCODEC_SupportModuleLineout
18 #define HAL_WM8904_PLAY_CAPABILITY                                                                      \
19     kCODEC_SupportPlayChannelLeft0 | kCODEC_SupportPlayChannelRight0 | kCODEC_SupportPlayChannelLeft1 | \
20         kCODEC_SupportPlayChannelRight1 | kCODEC_SupportPlaySourcePGA | kCODEC_SupportPlaySourceDAC
21 #define HAL_WM8904_VOLUME_CAPABILITY                                                                    \
22     kCODEC_SupportPlayChannelLeft0 | kCODEC_SupportPlayChannelRight0 | kCODEC_SupportPlayChannelLeft1 | \
23         kCODEC_SupportPlayChannelRight1 | kCODEC_VolumeDAC
24 #define HAL_WM8904_RECORD_CAPABILITY                                                                             \
25     kCODEC_SupportRecordSourceDifferentialLine | kCODEC_SupportRecordSourceDifferentialMic |                     \
26         kCODEC_SupportRecordSourceLineInput | kCODEC_SupportRecordSourceDigitalMic |                             \
27         kCODEC_SupportRecordChannelLeft1 | kCODEC_SupportRecordChannelLeft2 | kCODEC_SupportRecordChannelLeft3 | \
28         kCODEC_SupportRecordChannelRight1 | kCODEC_SupportRecordChannelRight2 | kCODEC_SupportRecordChannelRight3
29 
30 /*! @brief wm8904 map protocol */
31 #define HAL_WM8904_MAP_PROTOCOL(protocol)                                      \
32     ((protocol) == kCODEC_BusI2S            ? kWM8904_ProtocolI2S :            \
33      (protocol) == kCODEC_BusLeftJustified  ? kWM8904_ProtocolLeftJustified :  \
34      (protocol) == kCODEC_BusRightJustified ? kWM8904_ProtocolRightJustified : \
35      (protocol) == kCODEC_BusPCMA           ? kWM8904_ProtocolPCMA :           \
36      (protocol) == kCODEC_BusPCMB           ? kWM8904_ProtocolPCMB :           \
37                                               kWM8904_ProtocolI2S)
38 
39 /*! @brief wm8904 map module */
40 #define HAL_WM8904_MAP_MODULE(module)                               \
41     ((module) == kCODEC_ModuleADC       ? kWM8904_ModuleADC :       \
42      (module) == kCODEC_ModuleDAC       ? kWM8904_ModuleDAC :       \
43      (module) == kCODEC_ModulePGA       ? kWM8904_ModulePGA :       \
44      (module) == kCODEC_ModuleHeadphone ? kWM8904_ModuleHeadphone : \
45      (module) == kCODEC_ModuleLineout   ? kWM8904_ModuleLineout :   \
46                                           kWM8904_ModuleADC)
47 
48 /*! @brief wm8904 map protocol */
49 #define HAL_WM8904_MAP_SAMPLERATE(sampleRATE)                                \
50     ((sampleRATE) == kCODEC_AudioSampleRate8KHz  ? kWM8904_SampleRate8kHz :  \
51      (sampleRATE) == kCODEC_AudioSampleRate12KHz ? kWM8904_SampleRate12kHz : \
52      (sampleRATE) == kCODEC_AudioSampleRate16KHz ? kWM8904_SampleRate16kHz : \
53      (sampleRATE) == kCODEC_AudioSampleRate24KHz ? kWM8904_SampleRate24kHz : \
54      (sampleRATE) == kCODEC_AudioSampleRate32KHz ? kWM8904_SampleRate32kHz : \
55                                                    kWM8904_SampleRate48kHz)
56 
57 /*******************************************************************************
58  * Prototypes
59  ******************************************************************************/
60 
61 /*******************************************************************************
62  * Variables
63  ******************************************************************************/
64 static const codec_capability_t s_wm8904_capability = {
65     .codecPlayCapability   = HAL_WM8904_PLAY_CAPABILITY,
66     .codecVolumeCapability = HAL_WM8904_VOLUME_CAPABILITY,
67     .codecModuleCapability = HAL_WM8904_MODULE_CAPABILITY,
68     .codecRecordCapability = HAL_WM8904_RECORD_CAPABILITY,
69 };
70 /*******************************************************************************
71  * Code
72  ******************************************************************************/
73 /*!
74  * brief Codec initilization.
75  *
76  * param handle codec handle.
77  * param config codec configuration.
78  * return kStatus_Success is success, else initial failed.
79  */
HAL_CODEC_WM8904_Init(void * handle,void * config)80 status_t HAL_CODEC_WM8904_Init(void *handle, void *config)
81 {
82     assert((config != NULL) && (handle != NULL));
83 
84     codec_config_t *codecConfig = (codec_config_t *)config;
85 
86     wm8904_config_t *devConfig = (wm8904_config_t *)(codecConfig->codecDevConfig);
87     wm8904_handle_t *devHandle = (wm8904_handle_t *)((uint32_t)(((codec_handle_t *)handle)->codecDevHandle));
88 
89     ((codec_handle_t *)handle)->codecCapability = &s_wm8904_capability;
90 
91     /* codec device initialization */
92     return WM8904_Init(devHandle, devConfig);
93 }
94 
95 /*!
96  * brief Codec de-initilization.
97  *
98  * param handle codec handle.
99  * return kStatus_Success is success, else de-initial failed.
100  */
HAL_CODEC_WM8904_Deinit(void * handle)101 status_t HAL_CODEC_WM8904_Deinit(void *handle)
102 {
103     assert(handle != NULL);
104 
105     return WM8904_Deinit((wm8904_handle_t *)((uint32_t)(((codec_handle_t *)handle)->codecDevHandle)));
106 }
107 
108 /*!
109  * brief set audio data format.
110  *
111  * param handle codec handle.
112  * param mclk master clock frequency in HZ.
113  * param sampleRate sample rate in HZ.
114  * param bitWidth bit width.
115  * return kStatus_Success is success, else configure failed.
116  */
HAL_CODEC_WM8904_SetFormat(void * handle,uint32_t mclk,uint32_t sampleRate,uint32_t bitWidth)117 status_t HAL_CODEC_WM8904_SetFormat(void *handle, uint32_t mclk, uint32_t sampleRate, uint32_t bitWidth)
118 {
119     assert(handle != NULL);
120     status_t ret = kStatus_Success;
121 
122     ret = WM8904_SetAudioFormat((wm8904_handle_t *)((uint32_t)(((codec_handle_t *)handle)->codecDevHandle)), mclk,
123                                 sampleRate, bitWidth);
124     if (ret != kStatus_Success)
125     {
126         return ret;
127     }
128 
129     return kStatus_Success;
130 }
131 
132 /*!
133  * brief set audio codec module volume.
134  *
135  * param handle codec handle.
136  * param channel audio codec play channel, can be a value or combine value of _codec_play_channel.
137  * param volume volume value, support 0 ~ 100, 0 is mute, 100 is the maximum volume value.
138  * return kStatus_Success is success, else configure failed.
139  */
HAL_CODEC_WM8904_SetVolume(void * handle,uint32_t playChannel,uint32_t volume)140 status_t HAL_CODEC_WM8904_SetVolume(void *handle, uint32_t playChannel, uint32_t volume)
141 {
142     assert(handle != NULL);
143     assert(volume <= CODEC_VOLUME_MAX_VALUE);
144 
145     uint32_t mappedVolume = 0;
146     status_t ret          = kStatus_Success;
147 
148     if ((playChannel & ((uint32_t)kCODEC_VolumeDAC)) != 0U)
149     {
150         mappedVolume = (volume * (WM8904_DAC_MAX_VOLUME - 0U)) / 100U;
151         ret          = WM8904_SetDACVolume((wm8904_handle_t *)((uint32_t)(((codec_handle_t *)handle)->codecDevHandle)),
152                                            (uint8_t)mappedVolume);
153         if (ret != kStatus_Success)
154         {
155             return ret;
156         }
157     }
158 
159     if ((playChannel & ((uint32_t)kCODEC_PlayChannelLeft0 | (uint32_t)kCODEC_PlayChannelRight0 |
160                         (uint32_t)kCODEC_PlayChannelLeft1 | (uint32_t)kCODEC_PlayChannelRight1)) != 0U)
161     {
162         /* 0 will mute the output */
163         if (volume == 0U)
164         {
165             ret = WM8904_SetChannelMute((wm8904_handle_t *)((uint32_t)(((codec_handle_t *)handle)->codecDevHandle)),
166                                         playChannel, true);
167         }
168         else
169         {
170             /* 1-100 mapped to 0-63 */
171             mappedVolume = ((volume - 1U) * (WM8904_MAP_HEADPHONE_LINEOUT_MAX_VOLUME + 1U)) / 100U;
172 
173             ret = WM8904_SetChannelVolume((wm8904_handle_t *)((uint32_t)(((codec_handle_t *)handle)->codecDevHandle)),
174                                           playChannel, mappedVolume);
175             if (ret == kStatus_Success)
176             {
177                 ret = WM8904_SetChannelMute((wm8904_handle_t *)((uint32_t)(((codec_handle_t *)handle)->codecDevHandle)),
178                                             playChannel, false);
179             }
180         }
181     }
182 
183     return ret;
184 }
185 
186 /*!
187  * brief set audio codec module mute.
188  *
189  * param handle codec handle.
190  * param channel audio codec play channel, can be a value or combine value of _codec_play_channel.
191  * param isMute true is mute, false is unmute.
192  * return kStatus_Success is success, else configure failed.
193  */
HAL_CODEC_WM8904_SetMute(void * handle,uint32_t playChannel,bool isMute)194 status_t HAL_CODEC_WM8904_SetMute(void *handle, uint32_t playChannel, bool isMute)
195 {
196     assert(handle != NULL);
197 
198     return WM8904_SetChannelMute((wm8904_handle_t *)((uint32_t)(((codec_handle_t *)handle)->codecDevHandle)),
199                                  playChannel, isMute);
200 }
201 
202 /*!
203  * brief set audio codec module power.
204  *
205  * param handle codec handle.
206  * param module audio codec module.
207  * param powerOn true is power on, false is power down.
208  * return kStatus_Success is success, else configure failed.
209  */
HAL_CODEC_WM8904_SetPower(void * handle,uint32_t module,bool powerOn)210 status_t HAL_CODEC_WM8904_SetPower(void *handle, uint32_t module, bool powerOn)
211 {
212     assert(handle != NULL);
213     status_t ret = kStatus_Success;
214 
215     ret = WM8904_SetModulePower((wm8904_handle_t *)((uint32_t)(((codec_handle_t *)handle)->codecDevHandle)),
216                                 HAL_WM8904_MAP_MODULE((codec_module_t)module), powerOn);
217 
218     if (ret != kStatus_Success)
219     {
220         return ret;
221     }
222 
223     return kStatus_Success;
224 }
225 
226 /*!
227  * brief codec set record source.
228  *
229  * param handle codec handle.
230  * param source audio codec record source, can be a value or combine value of _codec_record_source.
231  *
232  * return kStatus_Success is success, else configure failed.
233  */
HAL_CODEC_WM8904_SetRecord(void * handle,uint32_t recordSource)234 status_t HAL_CODEC_WM8904_SetRecord(void *handle, uint32_t recordSource)
235 {
236     assert(handle != NULL);
237     status_t ret = kStatus_Success;
238 
239     ret = WM8904_SetRecord((wm8904_handle_t *)((uint32_t)(((codec_handle_t *)handle)->codecDevHandle)), recordSource);
240 
241     if (ret != kStatus_Success)
242     {
243         return ret;
244     }
245 
246     return kStatus_Success;
247 }
248 
249 /*!
250  * brief codec set record channel.
251  *
252  * param handle codec handle.
253  * param leftRecordChannel audio codec record channel, reference _codec_record_channel, can be a value or combine value
254  of member in _codec_record_channel.
255  * param rightRecordChannel audio codec record channel, reference _codec_record_channel, can be a value combine of
256  member in _codec_record_channel.
257 
258  * return kStatus_Success is success, else configure failed.
259  */
HAL_CODEC_WM8904_SetRecordChannel(void * handle,uint32_t leftRecordChannel,uint32_t rightRecordChannel)260 status_t HAL_CODEC_WM8904_SetRecordChannel(void *handle, uint32_t leftRecordChannel, uint32_t rightRecordChannel)
261 {
262     assert(handle != NULL);
263 
264     return WM8904_SetRecordChannel((wm8904_handle_t *)((uint32_t)(((codec_handle_t *)handle)->codecDevHandle)),
265                                    leftRecordChannel, rightRecordChannel);
266 }
267 
268 /*!
269  * brief codec set play source.
270  *
271  * param handle codec handle.
272  * param playSource audio codec play source, can be a value or combine value of _codec_play_source.
273  *
274  * return kStatus_Success is success, else configure failed.
275  */
HAL_CODEC_WM8904_SetPlay(void * handle,uint32_t playSource)276 status_t HAL_CODEC_WM8904_SetPlay(void *handle, uint32_t playSource)
277 {
278     assert(handle != NULL);
279 
280     return WM8904_SetPlay((wm8904_handle_t *)((uint32_t)(((codec_handle_t *)handle)->codecDevHandle)), playSource);
281 }
282 
283 /*!
284  * brief codec module control.
285  *
286  * param handle codec handle.
287  * param cmd module control cmd, reference _codec_module_ctrl_cmd.
288  * param data value to write, when cmd is kCODEC_ModuleRecordSourceChannel, the data should be a value combine
289  *  of channel and source, please reference macro CODEC_MODULE_RECORD_SOURCE_CHANNEL(source, LP, LN, RP, RN), reference
290  *  codec specific driver for detail configurations.
291  * return kStatus_Success is success, else configure failed.
292  */
HAL_CODEC_WM8904_ModuleControl(void * handle,uint32_t cmd,uint32_t data)293 status_t HAL_CODEC_WM8904_ModuleControl(void *handle, uint32_t cmd, uint32_t data)
294 {
295     return kStatus_CODEC_NotSupport;
296 }
297