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