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