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