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, &regVal) != 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, &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