1 /*
2  * Copyright  2021-2023 NXP
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include "fsl_codec_wm8960_adapter.h"
8 #include "fsl_codec_common.h"
9 /*******************************************************************************
10  * Definitions
11  ******************************************************************************/
12 /*! @brief module capability definition */
13 #define HAL_WM8960_MODULE_CAPABILITY                                                                                   \
14     (kCODEC_SupportModuleADC | kCODEC_SupportModuleDAC | kCODEC_SupportModuleHeadphone | kCODEC_SupportModuleLineout | \
15      kCODEC_SupportModuleSpeaker | kCODEC_SupportModuleMic | kCODEC_SupportModuleMixer | kCODEC_SupportModuleMicbias | \
16      kCODEC_SupportModuleVref | kCODEC_SupportModuleLinein)
17 
18 #define HAL_WM8960_PLAY_CAPABILITY                                                                       \
19     (kCODEC_SupportPlayChannelLeft0 | kCODEC_SupportPlayChannelRight0 | kCODEC_SupportPlayChannelLeft1 | \
20      kCODEC_SupportPlayChannelRight1 | kCODEC_SupportPlaySourcePGA | kCODEC_SupportPlaySourceDAC |       \
21      kCODEC_SupportPlaySourceInput)
22 
23 #define HAL_WM8960_VOLUME_CAPABILITY                                                                     \
24     (kCODEC_SupportPlayChannelLeft0 | kCODEC_SupportPlayChannelRight0 | kCODEC_SupportPlayChannelLeft1 | \
25      kCODEC_SupportPlayChannelRight1 | kCODEC_VolumeDAC)
26 
27 #define HAL_WM8960_RECORD_CAPABILITY                                                                    \
28     (kCODEC_SupportPlayChannelLeft0 | kCODEC_SupportPlayChannelLeft1 | kCODEC_SupportPlayChannelLeft2 | \
29      kCODEC_SupportPlayChannelRight0 | kCODEC_SupportPlayChannelRight1 | kCODEC_SupportPlayChannelRight2)
30 
31 /*! @brief wm8960 map protocol */
32 #define HAL_WM8960_MAP_PROTOCOL(protocol)                                 \
33     ((protocol) == kCODEC_BusI2S            ? kWM8960_BusI2S :            \
34      (protocol) == kCODEC_BusLeftJustified  ? kWM8960_BusLeftJustified :  \
35      (protocol) == kCODEC_BusRightJustified ? kWM8960_BusRightJustified : \
36      (protocol) == kCODEC_BusPCMA           ? kWM8960_BusPCMA :           \
37      (protocol) == kCODEC_BusPCMB           ? kWM8960_BusPCMB :           \
38                                               kWM8960_BusI2S)
39 
40 /*! @brief wm8960 map module */
41 #define HAL_WM8960_MAP_MODULE(module)                                       \
42     ((module) == (uint32_t)kCODEC_ModuleADC       ? kWM8960_ModuleADC :     \
43      (module) == (uint32_t)kCODEC_ModuleDAC       ? kWM8960_ModuleDAC :     \
44      (module) == (uint32_t)kCODEC_ModuleVref      ? kWM8960_ModuleVREF :    \
45      (module) == (uint32_t)kCODEC_ModuleHeadphone ? kWM8960_ModuleHP :      \
46      (module) == (uint32_t)kCODEC_ModuleMicbias   ? kWM8960_ModuleMICB :    \
47      (module) == (uint32_t)kCODEC_ModuleMic       ? kWM8960_ModuleMIC :     \
48      (module) == (uint32_t)kCODEC_ModuleLinein    ? kWM8960_ModuleLineIn :  \
49      (module) == (uint32_t)kCODEC_ModuleSpeaker   ? kWM8960_ModuleSpeaker : \
50      (module) == (uint32_t)kCODEC_ModuleMixer     ? kWM8960_ModuleOMIX :    \
51      (module) == (uint32_t)kCODEC_ModuleLineout   ? kWM8960_ModuleLineOut : \
52                                                     kWM8960_ModuleADC)
53 
54 /*******************************************************************************
55  * Prototypes
56  ******************************************************************************/
57 
58 /*******************************************************************************
59  * Variables
60  ******************************************************************************/
61 static const codec_capability_t s_wm8960_capability = {
62     .codecPlayCapability   = HAL_WM8960_PLAY_CAPABILITY,
63     .codecVolumeCapability = HAL_WM8960_VOLUME_CAPABILITY,
64     .codecModuleCapability = HAL_WM8960_MODULE_CAPABILITY,
65     .codecRecordCapability = HAL_WM8960_RECORD_CAPABILITY,
66 };
67 /*******************************************************************************
68  * Code
69  ******************************************************************************/
70 /*!
71  * brief Codec initilization.
72  *
73  * param handle codec handle.
74  * param config codec configuration.
75  * return kStatus_Success is success, else initial failed.
76  */
HAL_CODEC_WM8960_Init(void * handle,void * config)77 status_t HAL_CODEC_WM8960_Init(void *handle, void *config)
78 {
79     assert((config != NULL) && (handle != NULL));
80 
81     codec_config_t *codecConfig = (codec_config_t *)config;
82 
83     wm8960_config_t *devConfig = (wm8960_config_t *)(codecConfig->codecDevConfig);
84     wm8960_handle_t *devHandle = (wm8960_handle_t *)((uintptr_t)(((codec_handle_t *)handle)->codecDevHandle));
85 
86     ((codec_handle_t *)handle)->codecCapability = &s_wm8960_capability;
87 
88     /* codec device initialization */
89     return WM8960_Init(devHandle, devConfig);
90 }
91 
92 /*!
93  * brief Codec de-initilization.
94  *
95  * param handle codec handle.
96  * return kStatus_Success is success, else de-initial failed.
97  */
HAL_CODEC_WM8960_Deinit(void * handle)98 status_t HAL_CODEC_WM8960_Deinit(void *handle)
99 {
100     assert(handle != NULL);
101 
102     return WM8960_Deinit((wm8960_handle_t *)((uintptr_t)(((codec_handle_t *)handle)->codecDevHandle)));
103 }
104 
105 /*!
106  * brief set audio data format.
107  *
108  * param handle codec handle.
109  * param mclk master clock frequency in HZ.
110  * param sampleRate sample rate in HZ.
111  * param bitWidth bit width.
112  * return kStatus_Success is success, else configure failed.
113  */
HAL_CODEC_WM8960_SetFormat(void * handle,uint32_t mclk,uint32_t sampleRate,uint32_t bitWidth)114 status_t HAL_CODEC_WM8960_SetFormat(void *handle, uint32_t mclk, uint32_t sampleRate, uint32_t bitWidth)
115 {
116     assert(handle != NULL);
117 
118     return WM8960_ConfigDataFormat((wm8960_handle_t *)((uintptr_t)(((codec_handle_t *)handle)->codecDevHandle)), mclk,
119                                    sampleRate, bitWidth);
120 }
121 
122 /*!
123  * brief set audio codec module volume.
124  *
125  * param handle codec handle.
126  * param channel audio codec play channel, can be a value or combine value of _codec_play_channel.
127  * param volume volume value, support 0 ~ 100, 0 is mute, 100 is the maximum volume value.
128  * return kStatus_Success is success, else configure failed.
129  */
HAL_CODEC_WM8960_SetVolume(void * handle,uint32_t playChannel,uint32_t volume)130 status_t HAL_CODEC_WM8960_SetVolume(void *handle, uint32_t playChannel, uint32_t volume)
131 {
132     assert(handle != NULL);
133 
134     status_t retVal       = kStatus_Success;
135     uint32_t mappedVolume = 0U;
136 
137     if (((playChannel & (uint32_t)kWM8960_HeadphoneLeft) != 0U) ||
138         ((playChannel & (uint32_t)kWM8960_HeadphoneRight) != 0U))
139     {
140         /*
141          * 0 is mute
142          * 1 - 100 is mapped to 0x30 - 0x7F
143          */
144         mappedVolume = (volume * (WM8960_HEADPHONE_MAX_VOLUME_vALUE - WM8960_HEADPHONE_MIN_VOLUME_vALUE)) / 100U +
145                        WM8960_HEADPHONE_MIN_VOLUME_vALUE;
146         retVal = WM8960_SetVolume((wm8960_handle_t *)((uintptr_t)(((codec_handle_t *)handle)->codecDevHandle)),
147                                   kWM8960_ModuleHP, mappedVolume);
148     }
149 
150     if (((playChannel & (uint32_t)kWM8960_SpeakerLeft) != 0U) || ((playChannel & (uint32_t)kWM8960_SpeakerRight) != 0U))
151     {
152         /*
153          * 0 is mute
154          * 1 - 100 is mapped to 0x30 - 0x7F
155          */
156         mappedVolume = (volume * (WM8960_HEADPHONE_MAX_VOLUME_vALUE - WM8960_HEADPHONE_MIN_VOLUME_vALUE)) / 100U +
157                        WM8960_HEADPHONE_MIN_VOLUME_vALUE;
158         retVal = WM8960_SetVolume((wm8960_handle_t *)((uintptr_t)(((codec_handle_t *)handle)->codecDevHandle)),
159                                   kWM8960_ModuleSpeaker, mappedVolume);
160     }
161 
162     if ((playChannel & (uint32_t)kCODEC_VolumeDAC) != 0U)
163     {
164         /*
165          * 0 is mute
166          * 0 - 100 is mapped to 0x00 - 0xFF
167          */
168         mappedVolume = (volume * (WM8960_DAC_MAX_VOLUME_vALUE - 0U)) / 100U;
169 
170         retVal = WM8960_SetVolume((wm8960_handle_t *)((uintptr_t)(((codec_handle_t *)handle)->codecDevHandle)),
171                                   kWM8960_ModuleDAC, mappedVolume);
172     }
173 
174     return retVal;
175 }
176 
177 /*!
178  * brief set audio codec module mute.
179  *
180  * param handle codec handle.
181  * param channel audio codec play channel, can be a value or combine value of _codec_play_channel.
182  * param isMute true is mute, false is unmute.
183  * return kStatus_Success is success, else configure failed.
184  */
HAL_CODEC_WM8960_SetMute(void * handle,uint32_t playChannel,bool isMute)185 status_t HAL_CODEC_WM8960_SetMute(void *handle, uint32_t playChannel, bool isMute)
186 {
187     assert(handle != NULL);
188 
189     status_t retVal = kStatus_Success;
190 
191     if (((playChannel & (uint32_t)kWM8960_HeadphoneLeft) != 0U) ||
192         ((playChannel & (uint32_t)kWM8960_HeadphoneRight) != 0U))
193     {
194         retVal = WM8960_SetMute((wm8960_handle_t *)((uintptr_t)(((codec_handle_t *)handle)->codecDevHandle)),
195                                 kWM8960_ModuleHP, isMute);
196     }
197 
198     if (((playChannel & (uint32_t)kWM8960_SpeakerLeft) != 0U) || ((playChannel & (uint32_t)kWM8960_SpeakerRight) != 0U))
199     {
200         retVal = WM8960_SetMute((wm8960_handle_t *)((uintptr_t)(((codec_handle_t *)handle)->codecDevHandle)),
201                                 kWM8960_ModuleSpeaker, isMute);
202     }
203 
204     return retVal;
205 }
206 
207 /*!
208  * brief set audio codec module power.
209  *
210  * param handle codec handle.
211  * param module audio codec module.
212  * param powerOn true is power on, false is power down.
213  * return kStatus_Success is success, else configure failed.
214  */
HAL_CODEC_WM8960_SetPower(void * handle,uint32_t module,bool powerOn)215 status_t HAL_CODEC_WM8960_SetPower(void *handle, uint32_t module, bool powerOn)
216 {
217     assert(handle != NULL);
218 
219     return WM8960_SetModule((wm8960_handle_t *)((uintptr_t)(((codec_handle_t *)handle)->codecDevHandle)),
220                             HAL_WM8960_MAP_MODULE(module), powerOn);
221 }
222 
223 /*!
224  * brief codec set record channel.
225  *
226  * param handle codec handle.
227  * param leftRecordChannel audio codec record channel, reference _codec_record_channel, can be a value or combine value
228  of member in _codec_record_channel.
229  * param rightRecordChannel audio codec record channel, reference _codec_record_channel, can be a value combine of
230  member in _codec_record_channel.
231 
232  * return kStatus_Success is success, else configure failed.
233  */
HAL_CODEC_WM8960_SetRecordChannel(void * handle,uint32_t leftRecordChannel,uint32_t rightRecordChannel)234 status_t HAL_CODEC_WM8960_SetRecordChannel(void *handle, uint32_t leftRecordChannel, uint32_t rightRecordChannel)
235 {
236     return kStatus_CODEC_NotSupport;
237 }
238 
239 /*!
240  * brief codec set record source.
241  *
242  * param handle codec handle.
243  * param source audio codec record source, can be a value or combine value of _codec_record_source.
244  *
245  * @return kStatus_Success is success, else configure failed.
246  */
HAL_CODEC_WM8960_SetRecord(void * handle,uint32_t recordSource)247 status_t HAL_CODEC_WM8960_SetRecord(void *handle, uint32_t recordSource)
248 {
249     return kStatus_CODEC_NotSupport;
250 }
251 
252 /*!
253  * brief codec set play source.
254  *
255  * param handle codec handle.
256  * param playSource audio codec play source, can be a value or combine value of _codec_play_source.
257  *
258  * return kStatus_Success is success, else configure failed.
259  */
HAL_CODEC_WM8960_SetPlay(void * handle,uint32_t playSource)260 status_t HAL_CODEC_WM8960_SetPlay(void *handle, uint32_t playSource)
261 {
262     assert(handle != NULL);
263 
264     return WM8960_SetPlay((wm8960_handle_t *)((uintptr_t)(((codec_handle_t *)handle)->codecDevHandle)), playSource);
265 }
266 
267 /*!
268  * brief codec module control.
269  *
270  * param handle codec handle.
271  * param cmd module control cmd, reference _codec_module_ctrl_cmd.
272  * param data value to write, when cmd is kCODEC_ModuleRecordSourceChannel, the data should be a value combine
273  *  of channel and source, please reference macro CODEC_MODULE_RECORD_SOURCE_CHANNEL(source, LP, LN, RP, RN), reference
274  *  codec specific driver for detail configurations.
275  * return kStatus_Success is success, else configure failed.
276  */
HAL_CODEC_WM8960_ModuleControl(void * handle,uint32_t cmd,uint32_t data)277 status_t HAL_CODEC_WM8960_ModuleControl(void *handle, uint32_t cmd, uint32_t data)
278 {
279     return kStatus_CODEC_NotSupport;
280 }
281