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