• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &regVal) != 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, &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