1 /*
2 * Copyright (c) 2015, Freescale Semiconductor, Inc.
3 * Copyright 2016-2019 NXP
4 * Copyright (c) 2021 hpmicro
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 *
8 */
9
10 #include <stdio.h>
11 #include "hpm_sgtl5000.h"
12
13 #ifndef HPM_SGTL5000_MCLK_TOLERANCE
14 #define HPM_SGTL5000_MCLK_TOLERANCE (4U)
15 #endif
16
sgtl_init(sgtl_context_t * context,sgtl_config_t * config)17 hpm_stat_t sgtl_init(sgtl_context_t *context, sgtl_config_t *config)
18 {
19 assert(context != NULL);
20 assert(config != NULL);
21
22 if (sgtl_write_reg(context, CHIP_ANA_POWER, 0x6AFF) != status_success)
23 {
24 return status_fail;
25 }
26
27 /* Set the data route */
28 if (sgtl_set_data_route(context, config->route) != status_success)
29 {
30 return status_fail;
31 }
32
33 /* Set sgtl5000 to master or slave */
34 sgtl_set_master_mode(context, config->master);
35
36 /* Input Volume Control
37 Configure ADC left and right analog volume to desired default.
38 Example shows volume of 0dB. */
39 if (sgtl_write_reg(context, CHIP_ANA_ADC_CTRL, 0x0000U) != status_success)
40 {
41 return status_fail;
42 }
43
44 /* Volume and Mute Control
45 Configure HP_OUT left and right volume to minimum, unmute.
46 HP_OUT and ramp the volume up to desired volume.*/
47 if (sgtl_write_reg(context, CHIP_ANA_HP_CTRL, 0x0C0CU) != status_success)
48 {
49 return status_fail;
50 }
51
52 if (sgtl_modify_reg(context, CHIP_ANA_CTRL, 0xFFEFU, 0x0000U) != status_success)
53 {
54 return status_fail;
55 }
56
57 /* LINEOUT and DAC volume control */
58 if (sgtl_modify_reg(context, CHIP_ANA_CTRL, 0xFEFFU, 0x0000U) != status_success)
59 {
60 return status_fail;
61 }
62
63 /* Configure DAC left and right digital volume */
64 if (sgtl_write_reg(context, CHIP_DAC_VOL, 0x5C5CU) != status_success)
65 {
66 return status_fail;
67 }
68
69 /* Configure ADC volume, reduce 6db. */
70 if (sgtl_write_reg(context, CHIP_ANA_ADC_CTRL, 0x0100U) != status_success)
71 {
72 return status_fail;
73 }
74
75 /* Unmute DAC */
76 if (sgtl_modify_reg(context, CHIP_ADCDAC_CTRL, 0xFFFBU, 0x0000U) != status_success)
77 {
78 return status_fail;
79 }
80
81 if (sgtl_modify_reg(context, CHIP_ADCDAC_CTRL, 0xFFF7U, 0x0000U) != status_success)
82 {
83 return status_fail;
84 }
85
86 /* Unmute ADC */
87 if (sgtl_modify_reg(context, CHIP_ANA_CTRL, 0xFFFEU, 0x0000U) != status_success)
88 {
89 return status_fail;
90 }
91
92 /* Set the audio format */
93 if (sgtl_set_protocol(context, config->bus) != status_success)
94 {
95 return status_fail;
96 }
97
98 if (sgtl_config_data_format(context, config->format.mclk_hz, config->format.sample_rate, config->format.bit_width) !=
99 status_success)
100 {
101 return status_fail;
102 }
103
104 /* sclk valid edge */
105 if (config->format.sclk_edge == sgtl_sclk_valid_edge_rising)
106 {
107 if (sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_SCLK_INV_CLR_MASK, SGTL5000_I2S_VAILD_RISING_EDGE) !=
108 status_success)
109 {
110 return status_fail;
111 }
112 }
113 else
114 {
115 if (sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_SCLK_INV_CLR_MASK, SGTL5000_I2S_VAILD_FALLING_EDGE) !=
116 status_success)
117 {
118 return status_fail;
119 }
120 }
121
122 return status_success;
123 }
124
sgtl_deinit(sgtl_context_t * context)125 hpm_stat_t sgtl_deinit(sgtl_context_t *context)
126 {
127 hpm_stat_t stat = status_success;
128
129 HPM_CHECK_RET(sgtl_disable_module(context, sgtl_module_adc));
130 HPM_CHECK_RET(sgtl_disable_module(context, sgtl_module_dac));
131 HPM_CHECK_RET(sgtl_disable_module(context, sgtl_module_dap));
132 HPM_CHECK_RET(sgtl_disable_module(context, sgtl_module_i2sin));
133 HPM_CHECK_RET(sgtl_disable_module(context, sgtl_module_i2sout));
134 HPM_CHECK_RET(sgtl_disable_module(context, sgtl_module_lineout));
135
136 return stat;
137 }
138
sgtl_set_master_mode(sgtl_context_t * context,bool master)139 void sgtl_set_master_mode(sgtl_context_t *context, bool master)
140 {
141 if (master == true)
142 {
143 (void)sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_MS_CLR_MASK, SGTL5000_I2S_MASTER);
144 }
145 else
146 {
147 (void)sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_MS_CLR_MASK, SGTL5000_I2S_SLAVE);
148 }
149 }
150
sgtl_enable_module(sgtl_context_t * context,sgtl_module_t module)151 hpm_stat_t sgtl_enable_module(sgtl_context_t *context, sgtl_module_t module)
152 {
153 hpm_stat_t stat = status_success;
154 switch (module)
155 {
156 case sgtl_module_adc:
157 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_DIG_POWER, SGTL5000_ADC_ENABLE_CLR_MASK,
158 ((uint16_t)1U << SGTL5000_ADC_ENABLE_SHIFT)));
159 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_POWER, SGTL5000_ADC_POWERUP_CLR_MASK,
160 ((uint16_t)1U << SGTL5000_ADC_POWERUP_SHIFT)));
161 break;
162 case sgtl_module_dac:
163 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_DIG_POWER, SGTL5000_DAC_ENABLE_CLR_MASK,
164 ((uint16_t)1U << SGTL5000_DAC_ENABLE_SHIFT)));
165 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_POWER, SGTL5000_DAC_POWERUP_CLR_MASK,
166 ((uint16_t)1U << SGTL5000_DAC_POWERUP_SHIFT)));
167 break;
168 case sgtl_module_dap:
169 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_DIG_POWER, SGTL5000_DAP_ENABLE_CLR_MASK,
170 ((uint16_t)1U << SGTL5000_DAP_ENABLE_SHIFT)));
171 HPM_CHECK_RET(sgtl_modify_reg(context, SGTL5000_DAP_CONTROL, SGTL5000_DAP_CONTROL_DAP_EN_CLR_MASK,
172 ((uint16_t)1U << SGTL5000_DAP_CONTROL_DAP_EN_SHIFT)));
173 break;
174 case sgtl_module_i2sin:
175 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_DIG_POWER, SGTL5000_I2S_IN_ENABLE_CLR_MASK,
176 ((uint16_t)1U << SGTL5000_I2S_IN_ENABLE_SHIFT)));
177 break;
178 case sgtl_module_i2sout:
179 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_DIG_POWER, SGTL5000_I2S_OUT_ENABLE_CLR_MASK,
180 ((uint16_t)1U << SGTL5000_I2S_OUT_ENABLE_SHIFT)));
181 break;
182 case sgtl_module_hp:
183 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_POWER, SGTL5000_HEADPHONE_POWERUP_CLR_MASK,
184 ((uint16_t)1U << SGTL5000_HEADPHONE_POWERUP_SHIFT)));
185 break;
186 case sgtl_module_lineout:
187 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_POWER, SGTL5000_LINEOUT_POWERUP_CLR_MASK,
188 ((uint16_t)1U << SGTL5000_LINEOUT_POWERUP_SHIFT)));
189 break;
190 default:
191 stat = status_invalid_argument;
192 break;
193 }
194 return stat;
195 }
196
sgtl_disable_module(sgtl_context_t * context,sgtl_module_t module)197 hpm_stat_t sgtl_disable_module(sgtl_context_t *context, sgtl_module_t module)
198 {
199 hpm_stat_t stat = status_success;
200 switch (module)
201 {
202 case sgtl_module_adc:
203 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_DIG_POWER, SGTL5000_ADC_ENABLE_CLR_MASK,
204 ((uint16_t)0U << SGTL5000_ADC_ENABLE_SHIFT)));
205 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_POWER, SGTL5000_ADC_POWERUP_CLR_MASK,
206 ((uint16_t)0U << SGTL5000_ADC_POWERUP_SHIFT)));
207 break;
208 case sgtl_module_dac:
209 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_DIG_POWER, SGTL5000_DAC_ENABLE_CLR_MASK,
210 ((uint16_t)0U << SGTL5000_DAC_ENABLE_SHIFT)));
211 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_POWER, SGTL5000_DAC_POWERUP_CLR_MASK,
212 ((uint16_t)0U << SGTL5000_DAC_POWERUP_SHIFT)));
213 break;
214 case sgtl_module_dap:
215 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_DIG_POWER, SGTL5000_DAP_ENABLE_CLR_MASK,
216 ((uint16_t)0U << SGTL5000_DAP_ENABLE_SHIFT)));
217 HPM_CHECK_RET(sgtl_modify_reg(context, SGTL5000_DAP_CONTROL, SGTL5000_DAP_CONTROL_DAP_EN_CLR_MASK,
218 ((uint16_t)0U << SGTL5000_DAP_CONTROL_DAP_EN_SHIFT)));
219 break;
220 case sgtl_module_i2sin:
221 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_DIG_POWER, SGTL5000_I2S_IN_ENABLE_CLR_MASK,
222 ((uint16_t)0U << SGTL5000_I2S_IN_ENABLE_SHIFT)));
223 break;
224 case sgtl_module_i2sout:
225 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_DIG_POWER, SGTL5000_I2S_OUT_ENABLE_CLR_MASK,
226 ((uint16_t)0U << SGTL5000_I2S_OUT_ENABLE_SHIFT)));
227 break;
228 case sgtl_module_hp:
229 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_POWER, SGTL5000_HEADPHONE_POWERUP_CLR_MASK,
230 ((uint16_t)0U << SGTL5000_HEADPHONE_POWERUP_SHIFT)));
231 break;
232 case sgtl_module_lineout:
233 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_POWER, SGTL5000_LINEOUT_POWERUP_CLR_MASK,
234 ((uint16_t)0U << SGTL5000_LINEOUT_POWERUP_SHIFT)));
235 break;
236 default:
237 stat = status_invalid_argument;
238 break;
239 }
240 return stat;
241 }
242
sgtl_set_data_route(sgtl_context_t * context,sgtl_route_t route)243 hpm_stat_t sgtl_set_data_route(sgtl_context_t *context, sgtl_route_t route)
244 {
245 hpm_stat_t stat = status_success;
246 switch (route)
247 {
248 case sgtl_route_bypass:
249 /* Bypass means from line-in to HP*/
250 HPM_CHECK_RET(sgtl_write_reg(context, CHIP_DIG_POWER, 0x0000));
251 HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_hp));
252 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_CTRL, SGTL5000_SEL_HP_CLR_MASK, SGTL5000_SEL_HP_LINEIN));
253 break;
254 case sgtl_route_playback:
255 /* Data route I2S_IN-> DAC-> HP */
256 HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_hp));
257 HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_dac));
258 HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_i2sin));
259 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_SSS_CTRL, SGTL5000_DAC_SEL_CLR_MASK, SGTL5000_DAC_SEL_I2S_IN));
260 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_CTRL, SGTL5000_SEL_HP_CLR_MASK, SGTL5000_SEL_HP_DAC));
261 break;
262 case sgtl_route_playback_record:
263 /* I2S IN->DAC->HP LINE_IN->ADC->I2S_OUT */
264 HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_hp));
265 HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_dac));
266 HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_i2sin));
267 HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_i2sout));
268 HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_adc));
269 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_SSS_CTRL, SGTL5000_DAC_SEL_CLR_MASK, SGTL5000_DAC_SEL_I2S_IN));
270 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_CTRL, SGTL5000_SEL_HP_CLR_MASK, SGTL5000_SEL_HP_DAC));
271 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_CTRL, SGTL5000_SEL_ADC_CLR_MASK, SGTL5000_SEL_ADC_LINEIN));
272 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_SSS_CTRL, SGTL5000_I2S_OUT_SEL_CLR_MASK, SGTL5000_I2S_OUT_SEL_ADC));
273 break;
274 case sgtl_route_playback_with_dap:
275 /* I2S_IN->DAP->DAC->HP */
276 HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_hp));
277 HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_dac));
278 HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_i2sin));
279 HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_dap));
280 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_SSS_CTRL, SGTL5000_DAP_SEL_CLR_MASK, SGTL5000_DAP_SEL_I2S_IN));
281 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_SSS_CTRL, SGTL5000_DAC_SEL_CLR_MASK, SGTL5000_DAC_SEL_DAP));
282 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_CTRL, SGTL5000_SEL_HP_CLR_MASK, SGTL5000_SEL_HP_DAC));
283 break;
284 case sgtl_route_playback_with_dap_record:
285 /* I2S_IN->DAP->DAC->HP, LINE_IN->ADC->I2S_OUT */
286 HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_hp));
287 HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_dac));
288 HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_i2sin));
289 HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_i2sout));
290 HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_adc));
291 HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_dap));
292 HPM_CHECK_RET(sgtl_modify_reg(context, SGTL5000_DAP_CONTROL, SGTL5000_DAP_CONTROL_DAP_EN_CLR_MASK, 0x0001));
293 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_SSS_CTRL, SGTL5000_DAP_SEL_CLR_MASK, SGTL5000_DAP_SEL_I2S_IN));
294 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_SSS_CTRL, SGTL5000_DAC_SEL_CLR_MASK, SGTL5000_DAC_SEL_DAP));
295 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_CTRL, SGTL5000_SEL_HP_CLR_MASK, SGTL5000_SEL_HP_DAC));
296 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_CTRL, SGTL5000_SEL_ADC_CLR_MASK, SGTL5000_SEL_ADC_LINEIN));
297 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_SSS_CTRL, SGTL5000_I2S_OUT_SEL_CLR_MASK, SGTL5000_I2S_OUT_SEL_ADC));
298 break;
299 case sgtl_route_record:
300 /* LINE_IN->ADC->I2S_OUT */
301 HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_i2sout));
302 HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_adc));
303 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_CTRL, SGTL5000_SEL_ADC_CLR_MASK, SGTL5000_SEL_ADC_LINEIN));
304 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_SSS_CTRL, SGTL5000_I2S_OUT_SEL_CLR_MASK, SGTL5000_I2S_OUT_SEL_ADC));
305 break;
306 default:
307 stat = status_invalid_argument;
308 break;
309 }
310 return stat;
311 }
312
sgtl_set_protocol(sgtl_context_t * context,sgtl_protocol_t protocol)313 hpm_stat_t sgtl_set_protocol(sgtl_context_t *context, sgtl_protocol_t protocol)
314 {
315 hpm_stat_t stat = status_success;
316 switch (protocol)
317 {
318 case sgtl_bus_i2s:
319 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_MODE_CLR_MASK, SGTL5000_I2S_MODE_I2S_LJ));
320 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_LRALIGN_CLR_MASK, SGTL5000_I2S_ONE_BIT_DELAY));
321 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_SCLK_INV_CLR_MASK, SGTL5000_I2S_VAILD_RISING_EDGE));
322 break;
323 case sgtl_bus_left_justified:
324 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_MODE_CLR_MASK, SGTL5000_I2S_MODE_I2S_LJ));
325 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_LRALIGN_CLR_MASK, SGTL5000_I2S_NO_DELAY));
326 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_SCLK_INV_CLR_MASK, SGTL5000_I2S_VAILD_RISING_EDGE));
327 break;
328 case sgtl_bus_right_justified:
329 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_MODE_CLR_MASK, SGTL5000_I2S_MODE_RJ));
330 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_SCLK_INV_CLR_MASK, SGTL5000_I2S_VAILD_RISING_EDGE));
331 break;
332 case sgtl_bus_pcma:
333 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_MODE_CLR_MASK, SGTL5000_I2S_MODE_PCM));
334 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_LRALIGN_CLR_MASK, SGTL5000_I2S_ONE_BIT_DELAY));
335 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_SCLK_INV_CLR_MASK, SGTL5000_I2S_VAILD_FALLING_EDGE));
336 break;
337 case sgtl_bus_pcmb:
338 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_MODE_CLR_MASK, SGTL5000_I2S_MODE_PCM));
339 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_LRALIGN_CLR_MASK, SGTL5000_I2S_NO_DELAY));
340 HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_SCLK_INV_CLR_MASK, SGTL5000_I2S_VAILD_FALLING_EDGE));
341 break;
342 default:
343 stat = status_invalid_argument;
344 break;
345 }
346 return stat;
347 }
348
sgtl_set_volume(sgtl_context_t * context,sgtl_module_t module,uint32_t volume)349 hpm_stat_t sgtl_set_volume(sgtl_context_t *context, sgtl_module_t module, uint32_t volume)
350 {
351 uint16_t vol = 0;
352 hpm_stat_t stat = status_success;
353 switch (module)
354 {
355 case sgtl_module_adc:
356 if (volume > SGTL5000_ADC_MAX_VOLUME_VALUE)
357 {
358 return status_invalid_argument;
359 }
360
361 vol = (uint16_t)(volume | (volume << 4U));
362 stat = sgtl_modify_reg(context, CHIP_ANA_ADC_CTRL,
363 SGTL5000_ADC_VOL_LEFT_CLR_MASK & SGTL5000_ADC_VOL_RIGHT_CLR_MASK, vol);
364 break;
365 case sgtl_module_dac:
366 if ((volume > SGTL5000_DAC_MAX_VOLUME_VALUE) || (volume < SGTL5000_DAC_MIN_VOLUME_VALUE))
367 {
368 return status_invalid_argument;
369 }
370 vol = (uint16_t)(volume | (volume << 8U));
371 stat = sgtl_write_reg(context, CHIP_DAC_VOL, vol);
372 break;
373 case sgtl_module_hp:
374 if (volume > SGTL5000_HEADPHONE_MAX_VOLUME_VALUE)
375 {
376 return status_invalid_argument;
377 }
378 vol = (uint16_t)(volume | (volume << 8U));
379 stat = sgtl_write_reg(context, CHIP_ANA_HP_CTRL, vol);
380 break;
381 case sgtl_module_lineout:
382 if (volume > SGTL5000_LINE_OUT_MAX_VOLUME_VALUE)
383 {
384 return status_invalid_argument;
385 }
386 vol = (uint16_t)(volume | (volume << 8U));
387 stat = sgtl_write_reg(context, CHIP_LINE_OUT_VOL, vol);
388 break;
389 default:
390 stat = status_invalid_argument;
391 break;
392 }
393 return stat;
394 }
395
sgtl_get_volume(sgtl_context_t * context,sgtl_module_t module)396 uint32_t sgtl_get_volume(sgtl_context_t *context, sgtl_module_t module)
397 {
398 uint16_t vol = 0;
399 hpm_stat_t stat = status_success;
400
401 switch (module)
402 {
403 case sgtl_module_adc:
404 stat = sgtl_read_reg(context, CHIP_ANA_ADC_CTRL, &vol);
405 vol = (vol & (uint16_t)SGTL5000_ADC_VOL_LEFT_GET_MASK) >> SGTL5000_ADC_VOL_LEFT_SHIFT;
406 break;
407 case sgtl_module_dac:
408 stat = sgtl_read_reg(context, CHIP_DAC_VOL, &vol);
409 vol = (vol & (uint16_t)SGTL5000_DAC_VOL_LEFT_GET_MASK) >> SGTL5000_DAC_VOL_LEFT_SHIFT;
410 break;
411 case sgtl_module_hp:
412 stat = sgtl_read_reg(context, CHIP_ANA_HP_CTRL, &vol);
413 vol = (vol & (uint16_t)SGTL5000_HP_VOL_LEFT_GET_MASK) >> SGTL5000_HP_VOL_LEFT_SHIFT;
414 break;
415 case sgtl_module_lineout:
416 stat = sgtl_read_reg(context, CHIP_LINE_OUT_VOL, &vol);
417 vol = (vol & (uint16_t)SGTL5000_LINE_OUT_VOL_LEFT_GET_MASK) >> SGTL5000_LINE_OUT_VOL_LEFT_SHIFT;
418 break;
419 default:
420 vol = 0;
421 break;
422 }
423 return stat == status_success ? vol : 0U;
424 }
425
sgtl_set_mute(sgtl_context_t * context,sgtl_module_t module,bool mute)426 hpm_stat_t sgtl_set_mute(sgtl_context_t *context, sgtl_module_t module, bool mute)
427 {
428 hpm_stat_t stat = status_success;
429 switch (module)
430 {
431 case sgtl_module_adc:
432 stat = sgtl_modify_reg(context, CHIP_ANA_CTRL, SGTL5000_MUTE_ADC_CLR_MASK, mute ? 1U : 0U);
433 break;
434 case sgtl_module_dac:
435 if (mute)
436 {
437 stat = sgtl_modify_reg(context, CHIP_ADCDAC_CTRL,
438 SGTL5000_DAC_MUTE_LEFT_CLR_MASK & SGTL5000_DAC_MUTE_RIGHT_CLR_MASK, 0x000C);
439 }
440 else
441 {
442 stat = sgtl_modify_reg(context, CHIP_ADCDAC_CTRL,
443 SGTL5000_DAC_MUTE_LEFT_CLR_MASK & SGTL5000_DAC_MUTE_RIGHT_CLR_MASK, 0x0000);
444 }
445 break;
446 case sgtl_module_hp:
447 stat = sgtl_modify_reg(context, CHIP_ANA_CTRL, SGTL5000_MUTE_HP_CLR_MASK,
448 ((uint16_t)mute << SGTL5000_MUTE_HP_SHIFT));
449 break;
450 case sgtl_module_lineout:
451 stat = sgtl_modify_reg(context, CHIP_ANA_CTRL, SGTL5000_MUTE_LO_CLR_MASK,
452 ((uint16_t)mute << SGTL5000_MUTE_LO_SHIFT));
453 break;
454 default:
455 stat = status_invalid_argument;
456 break;
457 }
458 return stat;
459 }
460
sgtl_check_clock_tolerance(uint32_t source,uint32_t target)461 static bool sgtl_check_clock_tolerance(uint32_t source, uint32_t target)
462 {
463 uint32_t delta = (source >= target) ? (source - target) : (target - source);
464 if (delta * 100 <= HPM_SGTL5000_MCLK_TOLERANCE * target) {
465 return true;
466 }
467 return false;
468 }
469
sgtl_config_data_format(sgtl_context_t * context,uint32_t mclk,uint32_t sample_rate,uint32_t bits)470 hpm_stat_t sgtl_config_data_format(sgtl_context_t *context, uint32_t mclk, uint32_t sample_rate, uint32_t bits)
471 {
472 uint16_t val = 0;
473 uint16_t regVal = 0;
474 uint32_t mul_div = 0U;
475 uint32_t sysFs = 0U;
476 hpm_stat_t stat = status_success;
477
478 /* Over sample rate can only up to 512, the least to 8k */
479 if ((mclk / (MIN(sample_rate * 6U, 96000U)) > 512U) || (mclk / sample_rate < 256U))
480 {
481 return status_invalid_argument;
482 }
483
484 /* Configure the sample rate */
485 switch (sample_rate)
486 {
487 case 8000:
488 if (mclk > 32000U * 512U)
489 {
490 val = 0x0038;
491 sysFs = 48000;
492 }
493 else
494 {
495 val = 0x0020;
496 sysFs = 32000;
497 }
498 break;
499 case 11025:
500 val = 0x0024;
501 sysFs = 44100;
502 break;
503 case 12000:
504 val = 0x0028;
505 sysFs = 48000;
506 break;
507 case 16000:
508 if (mclk > 32000U * 512U)
509 {
510 val = 0x003C;
511 sysFs = 96000;
512 }
513 else
514 {
515 val = 0x0010;
516 sysFs = 32000;
517 }
518 break;
519 case 22050:
520 val = 0x0014;
521 sysFs = 44100;
522 break;
523 case 24000:
524 if (mclk > 48000U * 512U)
525 {
526 val = 0x002C;
527 sysFs = 96000;
528 }
529 else
530 {
531 val = 0x0018;
532 sysFs = 48000;
533 }
534 break;
535 case 32000:
536 val = 0x0000;
537 sysFs = 32000;
538 break;
539 case 44100:
540 val = 0x0004;
541 sysFs = 44100;
542 break;
543 case 48000:
544 if (mclk > 48000U * 512U)
545 {
546 val = 0x001C;
547 sysFs = 96000;
548 }
549 else
550 {
551 val = 0x0008;
552 sysFs = 48000;
553 }
554 break;
555 case 96000:
556 val = 0x000C;
557 sysFs = 96000;
558 break;
559 default:
560 stat = status_invalid_argument;
561 break;
562 }
563
564 if (stat != status_success)
565 {
566 return stat;
567 }
568
569 if (sgtl_read_reg(context, CHIP_I2S_CTRL, ®Val) != status_success)
570 {
571 return status_fail;
572 }
573
574 mul_div = mclk / sysFs;
575
576 if (sgtl_check_clock_tolerance(mul_div, 256)) {
577 mul_div = 256;
578 } else if (sgtl_check_clock_tolerance(mul_div, 384)) {
579 mul_div = 384;
580 } else if (sgtl_check_clock_tolerance(mul_div, 512)) {
581 mul_div = 512;
582 } else {
583 return status_invalid_argument;
584 }
585 val |= (mul_div / 128U - 2U);
586
587 if (sgtl_write_reg(context, CHIP_CLK_CTRL, val) != status_success)
588 {
589 return status_fail;
590 }
591
592 /* Data bits configure,sgtl supports 16bit, 20bit 24bit, 32bit */
593 if (sgtl_modify_reg(context, CHIP_I2S_CTRL, 0xFEFF, SGTL5000_I2S_SCLKFREQ_64FS) != status_success)
594 {
595 return status_fail;
596 }
597
598 switch (bits)
599 {
600 case 16:
601 stat = sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_DLEN_CLR_MASK, SGTL5000_I2S_DLEN_16);
602 break;
603 case 20:
604 stat = sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_DLEN_CLR_MASK, SGTL5000_I2S_DLEN_20);
605 break;
606 case 24:
607 stat = sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_DLEN_CLR_MASK, SGTL5000_I2S_DLEN_24);
608 break;
609 case 32:
610 stat = sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_DLEN_CLR_MASK, SGTL5000_I2S_DLEN_32);
611 break;
612 default:
613 stat = status_invalid_argument;
614 break;
615 }
616
617 return stat;
618 }
619
sgtl_set_play(sgtl_context_t * context,uint32_t playSource)620 hpm_stat_t sgtl_set_play(sgtl_context_t *context, uint32_t playSource)
621 {
622 uint16_t regValue = 0U, regBitMask = 0x40U;
623
624 /* headphone source form PGA */
625 if (playSource == (uint32_t)sgtl_play_source_linein)
626 {
627 regValue = 0x40U;
628 }
629 /* headphone source from DAC */
630 else
631 {
632 regValue = 0U;
633 }
634
635 return sgtl_modify_reg(context, CHIP_ANA_CTRL, regBitMask, regValue);
636 }
637
sgtl_set_record(sgtl_context_t * context,uint32_t recordSource)638 hpm_stat_t sgtl_set_record(sgtl_context_t *context, uint32_t recordSource)
639 {
640 uint16_t regValue = 0U, regBitMask = 0x4U;
641
642 /* ADC source form LINEIN */
643 if (recordSource == (uint32_t)sgtl_record_source_linein)
644 {
645 regValue = 0x4U;
646 }
647 /* ADC source from MIC */
648 else
649 {
650 regValue = 0U;
651 }
652
653 return sgtl_modify_reg(context, CHIP_ANA_CTRL, regBitMask, regValue);
654 }
655
sgtl_write_reg(sgtl_context_t * context,uint16_t reg,uint16_t val)656 hpm_stat_t sgtl_write_reg(sgtl_context_t *context, uint16_t reg, uint16_t val)
657 {
658 rt_size_t size;
659 rt_uint8_t data[4];
660 data[0] = reg >> 8;
661 data[1] = reg & 0xFF;
662 data[2] = (uint8_t) (val>>8);
663 data[3] = (uint8_t) (val & 0xFF);
664 size = rt_i2c_master_send(context->i2c_bus, context->slave_address, RT_I2C_WR, data, 4U);
665 if (size != 4) {
666 return status_fail;
667 }
668 return status_success;
669 }
670
sgtl_read_reg(sgtl_context_t * context,uint16_t reg,uint16_t * val)671 hpm_stat_t sgtl_read_reg(sgtl_context_t *context, uint16_t reg, uint16_t *val)
672 {
673 rt_size_t size;
674 rt_uint8_t r[2];
675 uint8_t d[2];
676 r[0] = reg >> 8;
677 r[1] = reg & 0xFF;
678
679 size = rt_i2c_master_send(context->i2c_bus, context->slave_address, RT_I2C_WR, r, 2U);
680 if (size != 2) {
681 return status_fail;
682 }
683
684 size = rt_i2c_master_recv(context->i2c_bus, context->slave_address, RT_I2C_RD, d, 2U);
685 if (size != 2) {
686 return status_fail;
687 }
688 *val = (uint16_t)((d[0] << 8) | d[1]);
689 return status_success;
690 }
691
sgtl_modify_reg(sgtl_context_t * context,uint16_t reg,uint16_t clr_mask,uint16_t val)692 hpm_stat_t sgtl_modify_reg(sgtl_context_t *context, uint16_t reg, uint16_t clr_mask, uint16_t val)
693 {
694 hpm_stat_t retval = 0;
695 uint16_t reg_val;
696
697 /* Read the register value out */
698 retval = sgtl_read_reg(context, reg, ®_val);
699 if (retval != status_success)
700 {
701 return status_fail;
702 }
703
704 /* Modify the value */
705 reg_val &= clr_mask;
706 reg_val |= val;
707
708 /* Write the data to register */
709 retval = sgtl_write_reg(context, reg, reg_val);
710 if (retval != status_success)
711 {
712 return status_fail;
713 }
714
715 return status_success;
716 }
717