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